Получить индекс заданного элемента в поле массива в 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
Другие вопросы по тегам