Как перевести NOT (A и B) в запрос mongodb - PullRequest
4 голосов
/ 11 июня 2019

Я построил грамматику (используя peg.js) для поддержки простых поисковых запросов в веб-приложении Node.js; Мне нужно перевести AST, который он выдает, в параметр $match для агрегатной функции MongoDB. В большинстве случаев все в порядке, но я не могу понять, как NOT (A AND B) должен выглядеть в MongoDB.

Некоторые примеры данных:

{ _id:123, labels:['a', 'b', 'c'], tags:['g', 'h', 'i']},
{ _id:456, labels:['a', 'e', 'f'], tags:['i', 'j', 'k']},
{ _id:789, labels:['c', 'd', 'b'], tags:['h', 'l', 'm']}

Пользователь может ввести запрос NOT (labels:a AND labels:b) или NOT (labels:b AND tags:h), которые являются действительными запросами, основываясь на моей грамматике.

Цель первого запроса - вернуть все документы, которые не содержат как 'a', так и 'b' в их поле labels (поэтому будут возвращены второй и третий документы); для второго запроса он должен соответствовать всем документам, которые не содержат как 'b' в поле labels, так и 'h' в поле tags.

Оператор $not MongoDB, похоже, не позволяет вам аккуратно отрицать логическую операцию так, как я ищу; в идеале я хотел бы сделать что-то вроде:

{
    $not: {
        $and: [
            { labels: a},
            { labels: b},
        ]
    }
}

или

{
    $not: {
        $and: [
            { labels: b},
            { tags: h},
        ]
    }
}

Есть ли другой оператор, который я могу использовать для этого? Кроме того, в идеале, это было бы легко создать программно, чтобы я мог построить потенциально сложный сложный запрос в скобках, а затем просто отменить его, если было NOT.

РЕДАКТИРОВАТЬ : Расширил набор данных, расширил и уточнил мои фактические требования к ответу.

1 Ответ

1 голос
/ 11 июня 2019

Для одного поля (согласно исходному вопросу) это должно сделать:

{
    'labels': {
        '$not': {
            '$all': [
                'a',
                'b',
            ]
        }
    }
}

Для нескольких полей вам нужно их разбить, но этот запрос будет работать:

{
    '$and': [
        {
            'labels': {
                '$not': {
                    '$all': ['b'],
                },
            },
        },
        {
            'tags': {
                '$not': {
                    '$all': ['h'],
                }
            }
        }
    ]
}

Я не думаю, что это возможно, чтобы не в качестве основного корневого элемента

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...