#mongodb #mongodb-query
#mongodb #mongodb-запрос
Вопрос:
Я пытаюсь оптимизировать запрос формы A.X = value OR B.Y.Z = value OR C.H = value
в Mongodb. Механизм БД использует 3 разных индекса для выполнения подобного запроса, а затем объединяет результаты. Это несколько медленно, поэтому я решил поместить все в один массив и создать для него индекс с несколькими ключами. Итак, я создал индекс и этот запрос для обновления записей и его заполнения:
{
'$addFields': {
'AllowedEntries': [ '$A.X', '$B.Y.Z', '$C.H' ]
}
}
Это сработало как шарм, но потом я понял, что некоторые значения являются нулевыми, и я хочу, чтобы нули были удалены из массива. Итак, я перешел к этому запросу:
{
'$addFields': {
'AllowedEntries': {
'$map': {
'input': [ '$A.X', '$B.Y.Z', '$C.H' ],
'as': 'item',
'in': {
'columns': {
'$filter': {
'input': '$$item',
'as': 'elt',
'cond': { '$ne': [ '$$elt', null ] }
}
}
}
}
}
}
}
Который не работает из-за input to $filter must be an array not binData
ошибки. Как я могу сделать это атомарно? Теоретически я мог бы выполнить этот запрос, а затем извлечь нули, но мне бы очень хотелось сделать это за одно обновление.
Комментарии:
1. $map не должен быть обязательным, $filter должен быть в состоянии это сделать.
2. Не могли бы вы привести пример? Я не уверен, что понял вашу идею
3. Оператор $filter предназначен для выбора элементов из массива на основе логического условия, что вы и пытаетесь сделать. Посмотрите пример на docs.mongodb.com/manual/reference/operator/aggregation/filter /…
4. Прохладный. Сработало как шарм. Возможно ли не получать только уникальные значения? Я пытался
$addToSet
, но не удалось. Также вы не хотите опубликовать ответ? Я отмечу это, так как это помогло мне.
Ответ №1:
В итоге я пришел к следующему решению: поместить уникальные ненулевые элементы в новое поле. Большое спасибо @Joe за помощь
{
'$addFields': {
'AllowedEntries': {
'$setUnion': [[], {
'$filter': {
'input': [ '$A.X', '$B.Y.Z', '$C.H' ],
'as': 'elt',
'cond': '$$elt'
}
}]
}
}
}
обратите внимание, что $setUnion
вместо используется с пустым массивом $addToSet
, потому что последний работает с именами столбцов, в то время как первый работает с любым выражением, которое в нашем случае является фильтром.