MongoDB ดำเนินการ $match ด้วยค่าอาร์เรย์อินพุตสองค่าหรือไม่

ใน MongoDB ฉันกำลังพยายามเขียนแบบสอบถามโดยที่ฉันมีอาร์เรย์อินพุตสองตัว Bills, Names โดยที่อันแรกมี billids และอันที่สองมีชื่อของบุคคล ในความเป็นจริง 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 สามารถทำงานในอาร์เรย์ของวัตถุได้ ฉันสามารถมีอาร์เรย์ของวัตถุที่มีคีย์เป็นการเรียกเก็บเงินและชื่อ

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 ไม่ใช่เช่นนั้น สมมติว่าตัวอย่าง DB คือ [{ billid : bnb1234, name: "michael"}, {billid : bnb1235, name: "michael"}] Bills = ["bnb1234", "bnb1235"] และ Names = ["michael", "michael"] ทีนี้ประเด็นก็คือเมื่อคุณจะใช้ $match เพื่อดูดัชนีของทั้งคู่ แล้วสำหรับดัชนีชื่ออันแรก จะเป็น 1 และดัชนี Bills จะเป็น 1 ดังนั้นจึงตรงกัน แต่สำหรับอันที่สองเนื่องจากดัชนี Bills คือ 2 แต่ดัชนี Names คือ 1 ไม่ใช่ 2(because Names are not unique) - 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