Получить индекс заданного элемента в поле массива в MongoDB
Подумайте об этом документе MongoDB:
{_id:123, "food":[ "apple", "banana", "mango" ]}
Вопрос: Как получить должность mango
в еду?
Запрос должен вернуть 2
выше, и не возвращайте весь документ.
Пожалуйста, покажите рабочий запрос.
3 ответа
Начиная с версии 3.4 MongoDB мы можем использовать $indexOfArray
оператор для возврата индекса, по которому данный элемент может быть найден в массиве.
$indexOfArray
принимает три аргумента. Первое имя поля массива с префиксом $
знак.
Вторым является элемент, а третьим необязательным является индекс, с которого начинается поиск. $indexOfArray
возвращает первый индекс, по которому был найден элемент, если не указан индекс, с которого начинается поиск.
Демо-версия:
> db.collection.insertOne( { "_id" : 123, "food": [ "apple", "mango", "banana", "mango" ] } )
{ "acknowledged" : true, "insertedId" : 123 }
> db.collection.aggregate( [ { "$project": { "matchedIndex": { "$indexOfArray": [ "$food", "mango" ] } } } ] )
{ "_id" : 123, "matchedIndex" : 1 }
> db.collection.aggregate( [ { "$project": { "matchedIndex": { "$indexOfArray": [ "$food", "mango", 2 ] } } } ] )
{ "_id" : 123, "matchedIndex" : 3 }
> db.collection.aggregate( [ { "$project": { "matchedIndex": { "$indexOfArray": [ "$food", "apricot" ] } } } ] )
{ "_id" : 123, "matchedIndex" : -1 }
Там действительно нет другого пути ( "на стороне сервера"), чем использование mapReduce
:
db.collection.mapReduce(
function() {
emit(this._id, this.food.indexOf("mango"));
},
function() {}, // reducer never gets called since all _id is unique
{
"out": { "inline": 1 },
"query": { "food": "mango" }
}
)
Это единственное, что будет возвращать что-то другое в измененной форме, кроме самого документа, а также использовать необходимую оценку JavaScript для определения ответа,
К сожалению, нет "родного" оператора, который бы это делал.
Если вам не нужно это для реальных целей агрегации, то лучше просто выполнить аналогичное "сопоставление индекса массива" в нативном коде вашего клиента при работе на основе "на документ".
В оболочке монго (также в Робомонго) я бы сделал следующее:
var food = db.getCollection('yourCollection').findOne({_id: '123'}).food;
print('Index of mango: ' + food.indexOf('mango'));
или вы можете сохранить этот код в any_file.js
а затем запустить из командной строки:
mongo your_db any_file.js
Это будет производить что-то вроде этого:
MongoDB shell version: 2.4.9
connecting to: localhost:27017/your_db
Index of mango: 2