วิธีสืบค้นวัตถุที่ซ้อนกัน


204

ฉันมีปัญหาเมื่อสอบถาม mongoDB ด้วยสัญกรณ์วัตถุที่ซ้อนกัน:

db.messages.find( { headers : { From: "reservations@marriott.com" } } ).count()
0
db.messages.find( { 'headers.From': "reservations@marriott.com" }  ).count()
5

ฉันไม่เห็นสิ่งที่ฉันทำผิด ฉันคาดหวังว่าสัญกรณ์วัตถุที่ซ้อนกันเพื่อกลับผลลัพธ์เช่นเดียวกับแบบสอบถามจุดสัญกรณ์ ฉันผิดตรงไหน

คำตอบ:


419

db.messages.find( { headers : { From: "reservations@marriott.com" } } )

แบบสอบถามนี้สำหรับเอกสารที่headers เท่ากับ { From: ... }คือไม่มีสาขาอื่น


db.messages.find( { 'headers.From': "reservations@marriott.com" } )

นี้มีลักษณะเฉพาะที่headers.Fromสนามไม่ได้รับผลกระทบจากสาขาอื่น ๆ headersที่มีอยู่ในหรือหายไปจาก


เอกสารดอทโน้ต


มีวิธีการทำเช่นนี้โดยไม่มีเครื่องหมายคำพูดรอบ "ส่วนหัวจาก"?
trysis

ฉันไม่รู้เพียงแค่สงสัยและคิดว่าบางครั้งมันอาจมีประโยชน์
trysis

3
@trysis - ในทางปฏิบัติฉันได้พบว่าการประกาศวัตถุอินไลน์ (เช่นตัวอย่างในเอกสาร Mongo [ose] docs และในตัวอย่างส่วนใหญ่มี) ไม่เพียงพอในโลกแห่งความจริง ฉันได้พัฒนานิสัยในการสร้างวัตถุ 'เงื่อนไข' และ 'ฟิลด์' ซึ่งฉันสามารถทำสิ่งต่าง ๆ เช่นconditions['some.path'] = 'value'ในตรรกะทางธุรกิจของฉันแล้วเรียกใช้แบบสอบถามเดียวในตอนท้าย:find(conditions, fields, callback);
Ryan Wheale

เกิดอะไรขึ้นถ้าของขอบอกว่าผมมีคีย์ซึ่งมี "domain.com" domains.domain.comนี้จะไม่ทำงาน: มีวิธีแก้ปัญหาสำหรับสถานการณ์นี้หรือไม่ (โดยไม่ต้องเปลี่ยน domain.com เป็นอย่างอื่นเช่น domain_com)
Rens Tillmann

1
ตอบความคิดเห็นของฉันเองดีที่สุดคือหลีกเลี่ยงการใช้จุดในคีย์ของคุณอย่างสมบูรณ์ ในการแก้ปัญหาของฉันฉันทิ้งโดเมนทั้งหมดเป็นกุญแจและสร้างชิ้น / อาร์เรย์แทน
Rens Tillmann

20

กลไกเคียวรีสองรายการทำงานในวิธีที่ต่างกันดังที่แนะนำในเอกสารที่ส่วนย่อยเอกสาร :

เมื่อฟิลด์เก็บเอกสารที่ฝัง (เช่นเอกสารย่อย ) คุณสามารถระบุเอกสารย่อยทั้งหมดเป็นค่าของฟิลด์หรือ "เข้าถึงลงใน" เอกสารย่อยโดยใช้เครื่องหมายจุดเพื่อระบุค่าสำหรับแต่ละฟิลด์ในเอกสารย่อย :

การจับคู่ความเท่าเทียมกันภายในเอกสารย่อยเลือกเอกสารหากเอกสารย่อยตรงกับเอกสารย่อยที่ระบุรวมถึงลำดับของฟิลด์


ในตัวอย่างต่อไปนี้เคียวรีจับคู่เอกสารทั้งหมดที่ค่าของผู้สร้างฟิลด์เป็นเอกสารย่อยที่มีเฉพาะฟิลด์ที่companyมีค่า'ABC123'และฟิลด์ที่addressมีค่า'123 Street'ตามลำดับที่แน่นอน:

db.inventory.find( {
    producer: {
        company: 'ABC123',
        address: '123 Street'
    }
});

8
ฉันกำลังจะบ้า เรื่องนี้ดูเหมือนว่าฉันจะไม่สอดคล้องกันมากเพราะเมื่อทำการสอบถามวัตถุก็สามารถจับคู่คุณสมบัติโดยตรงในลำดับใดก็ได้
Capaj

7

เนื่องจากมีความสับสนมากมายเกี่ยวกับการสืบค้น MongoDB ซึ่งมีเอกสารย่อยฉันคิดว่ามันคุ้มค่าที่จะอธิบายคำตอบข้างต้นด้วยตัวอย่าง:

ครั้งแรกฉันได้แทรกสองวัตถุในคอลเลกชันคือ: messageเป็น:

> db.messages.find().pretty()
{
    "_id" : ObjectId("5cce8e417d2e7b3fe9c93c32"),
    "headers" : {
        "From" : "reservations@marriott.com"
    }
}
{
    "_id" : ObjectId("5cce8eb97d2e7b3fe9c93c33"),
    "headers" : {
        "From" : "reservations@marriott.com",
        "To" : "kprasad.iitd@gmail.com"
    }
}
>

ดังนั้นผลลัพธ์ของแบบสอบถามคืออะไร: db.messages.find({headers: {From: "reservations@marriott.com"} }).count()

มันควรจะเป็นหนึ่งเพราะแบบสอบถามเหล่านี้สำหรับเอกสารที่headersเท่ากับวัตถุ{From: "reservations@marriott.com"}เท่านั้นเช่นไม่มีเขตข้อมูลอื่นหรือเราควรระบุทั้งเอกสารย่อยเป็นค่าของเขตข้อมูล

ดังนั้นตามคำตอบจาก @ Edmondo1984

ความเท่าเทียมกันตรงที่อยู่ในเอกสารย่อยเลือกเอกสารหากเอกสารย่อยตรงว่าเอกสารย่อยที่กำหนดรวมถึงการสั่งซื้อสนาม

จากข้อความข้างต้นผลลัพธ์แบบสอบถามด้านล่างควรเป็นอย่างไร

> db.messages.find({headers: {To: "kprasad.iitd@gmail.com", From: "reservations@marriott.com"}  }).count()
0

และถ้าเราจะเปลี่ยนลำดับFromและToเช่นเดียวกับเอกสารย่อยของเอกสารที่สอง

> db.messages.find({headers: {From: "reservations@marriott.com", To: "kprasad.iitd@gmail.com"}  }).count()
1

ดังนั้นมันตรงตรงที่ระบุย่อยเอกสารรวมทั้งการสั่งซื้อสนาม

สำหรับการใช้ตัวดำเนินการ dot ฉันคิดว่ามันชัดเจนสำหรับทุก ๆ คน มาดูผลลัพธ์ของการค้นหาด้านล่าง:

> db.messages.find( { 'headers.From': "reservations@marriott.com" }  ).count()
2

ฉันหวังว่าคำอธิบายเหล่านี้ด้วยตัวอย่างข้างต้นจะทำให้คนที่ชัดเจนมากขึ้นในแบบสอบถามพบกับเอกสารย่อย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.