Обновить документ, если значение не соответствует

Как в MongoDB пропустить обновление, если одно поле документа существует?

Чтобы привести пример, у меня есть следующая структура документа, и я хотел бы только update, если ключ link не совпадает.

{
    "_id": {
        "$oid": "56e9978732beb44a2f2ac6ae"
    },
    "domain": "example.co.uk",
    "good": [
        {
            "crawled": true,
            "added": {
                "$date": "2016-03-16T17:27:17.461Z"
            },
            "link": "/url-1"
        },
        {
            "crawled": false,
            "added": {
                "$date": "2016-03-16T17:27:17.461Z"
            },
            "link": "url-2"
        }

    ]
}

Мой запрос на обновление:

links.update({
    "domain": "example.co.uk"
    },
    {'$addToSet':
        {'good':
            {"crawled": False, 'link':"/url-1"} }}, True)

Часть проблемы заключается в том, что поле crawl может быть установлено на True или False, а дата также всегда будет разной — я не хочу добавлять в массив, если URL-адрес существует, независимо от статуса crawled.

Обновление: Просто для ясности, если URL-адрес не находится в документе, я хочу, чтобы он был добавлен в существующий массив, например, если было введено /url-3, документ будет выглядеть так:

{
    "_id": {
        "$oid": "56e9978732beb44a2f2ac6ae"
    },
    "domain": "example.co.uk",
    "good": [
        {
            "crawled": true,
            "added": {
                "$date": "2016-03-16T17:27:17.461Z"
            },
            "link": "/url-1"
        },
        {
            "crawled": false,
            "added": {
                "$date": "2016-03-16T17:27:17.461Z"
            },
            "link": "url-2"
        },
        {
            "crawled": false,
            "added": {
                "$date": "2016-04-16T17:27:17.461Z"
            },
            "link": "url-3"
        }

    ]
}

domain будет уникальным и специфичным для ссылки, и я хочу, чтобы он вставлял link в массив good, если он не существует, и ничего не делал, если он существует.


person Adders    schedule 19.05.2016    source источник
comment
Почему вы используете вариант upsert? Собираетесь ли вы вставить новый документ, если совпадения нет? Также является ли домен уникальным?   -  person styvane    schedule 21.05.2016
comment
Да domain будет уникальным для link - я думаю, что могу использовать его неправильно, я хочу, чтобы он вставлял ссылку в массив, если он не существует, и ничего не делал, если он существует   -  person Adders    schedule 21.05.2016


Ответы (2)


Единственный способ сделать это — найти в коллекции какой-либо документ, соответствующий вашим критериям, с помощью find_one, также вам необходимо учитывать поле "good.link" в критериях фильтрации. Если ни один документ не соответствует, вы запускаете запрос на обновление, используя update_one, но на этот раз вы не используете поле "good.link" в критериях запроса. Также вам не нужен оператор $addToSet, так как он ничего не делает просто используйте оператор обновления $push, это прояснит ваше намерение. Вам также не нужно «upsert» опцию здесь.

if not link.find_one({"domain": "example.co.uk", "good.link": "/url-1"}):
    link.update_one({"domain": "example.co.uk"}, 
                    {"$push": {"good": {"crawled": False, 'link':"/url-1"}}})
person styvane    schedule 19.05.2016
comment
Это работает! Хотя мне нужно было добавить опцию upsert обратно, иначе она не работает. Я предполагаю, что вы можете сделать это оптом из-за того, что это отдельные запросы? - person Adders; 21.05.2016

в разделе поиска запроса вы сопоставляете все документы, где

"domain": "example.co.uk"

вам нужно добавить, что вы не хотите совпадать

'good.link':"/url-1"

поэтому постарайтесь

{
    "domain": "example.co.uk",
    "good.link": {$ne: "/url-1"}
}
person Tiramisu    schedule 20.05.2016
comment
Я обновил свой вопрос, надеюсь, он будет более понятным, поскольку он добавляет новый документ, а не добавляет в массив - person Adders; 21.05.2016