MongoDB выполняет $ match с двумя значениями входного массива?

В MongoDB я пытаюсь написать запрос, в котором у меня есть два входных массива Bills, Names, где первый содержит биллиды, а второй - имена людей. Также на самом деле Bills в индексе i и Names в индексе i - это фактический документ, который мы хотим искать в MongoDB.

Я хочу написать такой запрос, чтобы Bills[i] = db_billid && Names[i] = db_name, что означает, что я хочу вернуть результат, в котором по определенному индексу совпадают и идентификатор, и имя.

Я думал об использовании $in, но дело в том, что я могу применить $in в Bills, но я не знаю, по какому индексу найден этот биллид.

{ $and: [{ billid: { $in: Bills } }, {name: Names[**index at which this bill is found]}] }

Может ли кто-нибудь помочь мне, как я могу это решить?

Схема MongoDB

var transactionsschema = new Schema({
    transactionid: {type: String},
    billid: {type: String},
    name: {type: String}
});

Образцы документов в MongoDB

{ _id: XXXXXXXXXXX, transactionid: 1, billid : bnb1234, name: "sudhanshu"}, { _id: XXXXXXXXXXX, transactionid: 2, billid : bnb1235, name: "michael"}, { _id: XXXXXXXXXXX, transactionid: 3, billid : bnb1236, name: "Morgot"}

Примеры массивов

Bills = ["bill1", "bill2", "bill3"], Names = ["name1", "name2", "name"]

Изменить - если $ in может работать с массивом объектов, тогда у меня может быть массив объектов с ключами, такими как billid и name.

var arr = [{billid: "bill1", "name": "name1"}, {billid: "bill2", "name": "name2"}, {billid: "bill3", "name": "name3" }]

Но дело в том, как поставить запрос ниже

{ $and: [{ billid: { $in: arr.Bills } }, {name: arr.Names}] }


person Sudhanshu Gaur    schedule 17.06.2018    source источник
comment
Не могли бы вы добавить образец документа и образцы счетов и имени?   -  person mickl    schedule 17.06.2018
comment
@mickl, подожди, позволь мне добавить.   -  person Sudhanshu Gaur    schedule 17.06.2018
comment
@mickl Я добавил образцы документов.   -  person Sudhanshu Gaur    schedule 17.06.2018


Ответы (1)


Зная, что bills уникальны, но names могут иметь дубликаты, вы можете использовать $ indexOfArray, чтобы получить индекс соответствия bill, а затем использовать этот индекс для сравнения массива names с оцененным индексом (используя $ arrayElemAt для получения значения). Также вы должны проверить, не равно ли значение, возвращаемое $indexOfArray, -1 (нет совпадения)

var bills = ["bnb1234", "bnb1235"];
var names = ["sudhanshu", "michael"];

db.col.aggregate([
    {
        $match: {
            $expr: {
                $and: [
                    { $ne: [{ $indexOfArray: [ bills, "$billid" ] }, -1] },
                    { $eq: ["$name", { $arrayElemAt: [ names, { $indexOfArray: [ bills, "$billid" ] } ] }] },
                ]
            }
        }
    }
])

в качестве альтернативы можно использовать $ let, чтобы избежать дублирования:

db.col.aggregate([
    {
        $match: {
            $expr: {
                $let: {
                    vars: { index: { $indexOfArray: [ bills, "$billid" ] } },
                    in: { $and: [ { $ne: [ "$$index", -1 ] }, { $eq: [ "$name", { $arrayElemAt: [ names, "$$index" ] }] }]}
                }
            }
        }
    }
])
person mickl    schedule 17.06.2018
comment
Предположим, у меня есть два вложенных запроса, первый - мой, а второй, решение которого вы предоставили, например `$ match: {$ and: {transactionid: 12345678}, {Your Query}}. Будет ли оно работать? Это правильно вложено или нет? - person Sudhanshu Gaur; 17.06.2018
comment
Вы можете добавить дополнительные условия к $match, например { $and: [ { $ne: ["$billIndex", -1] }, { $ne: ["$nameIndex", -1] }, { $eq: ["$billIndex", "$nameIndex"] }, { $eq: [ "$transactionId": 123 ] } ] }, это то, что вы имеете в виду? - person mickl; 17.06.2018
comment
Оставьте это, просто хотел спросить, поскольку Bills уникальные поля, но Names не так, предположим, что Sample DB - это [{ billid : bnb1234, name: "michael"}, {billid : bnb1235, name: "michael"}] Bills = ["bnb1234", "bnb1235"] и Names = ["michael", "michael"] Теперь дело в том, что когда вы будете использовать $match, чтобы увидеть индекс обоих из них, тогда для первого индекса имен будет 1, а индекс Bills будет 1, так что это совпадение, но для второго, так как индекс Bills равен 2, но индекс Names равен 1, а не _11 _ (_ 12_). - person Sudhanshu Gaur; 17.06.2018
comment
Итак, как я могу преодолеть это. Кстати, спасибо, что помог мне выбраться отсюда всего на одну строчку, близкую к решению :) - person Sudhanshu Gaur; 17.06.2018
comment
Только что нашел решение :) немного изменил ваш ответ, большое спасибо, чувак. Я упомянул решение в сообщении, измените свой ответ здесь, чтобы я мог его принять (y). - person Sudhanshu Gaur; 17.06.2018
comment
@SudhanshuGaur только что отредактировал мой ответ, что может быть проще, если вы используете arrayElemAt. Проверить мой отредактированный ответ - person mickl; 17.06.2018
comment
Ваш запрос возвращает все поля с name michael, но он должен возвращать только два документа. - person Sudhanshu Gaur; 17.06.2018
comment
Оба решения в некотором роде одинаковы, вы просто не использовали addFields. Когда мы addFields, делает ли запрос немного медленным? Потому что даже внутри вашего запроса, когда вы будете использовать names и bills, это также будет означать то же самое? - person Sudhanshu Gaur; 17.06.2018
comment
Спасибо, bdw, без тебя это было невозможно :) - person Sudhanshu Gaur; 17.06.2018