2013-04-24 29 views
51

İki koleksiyonları var.MongoDB: Bir dizi alan bir öğe içeriyorsa nasıl öğrenmek için?

{ "_id" : ObjectId("51780f796ec4051a536015cf"), "name" : "John" } 
{ "_id" : ObjectId("51780f796ec4051a536015d0"), "name" : "Sam" } 
{ "_id" : ObjectId("51780f796ec4051a536015d1"), "name" : "Chris" } 
{ "_id" : ObjectId("51780f796ec4051a536015d2"), "name" : "Joe" } 

ikinci toplama kursları içerir:: İlk toplama öğrencileri kapsar

{ 
     "_id" : ObjectId("51780fb5c9c41825e3e21fc4"), 
     "name" : "CS 101", 
     "students" : [ 
       ObjectId("51780f796ec4051a536015cf"), 
       ObjectId("51780f796ec4051a536015d0"), 
       ObjectId("51780f796ec4051a536015d2") 
     ] 
} 
{ 
     "_id" : ObjectId("51780fb5c9c41825e3e21fc5"), 
     "name" : "Literature", 
     "students" : [ 
       ObjectId("51780f796ec4051a536015d0"), 
       ObjectId("51780f796ec4051a536015d0"), 
       ObjectId("51780f796ec4051a536015d2") 
     ] 
} 
{ 
     "_id" : ObjectId("51780fb5c9c41825e3e21fc6"), 
     "name" : "Physics", 
     "students" : [ 
       ObjectId("51780f796ec4051a536015cf"), 
       ObjectId("51780f796ec4051a536015d0") 
     ] 
} 

Her ders belge kursu için kayıtlı öğrencilerin bir listesi vardır students dizi içerir. Bir öğrenci bir web sayfasındaki bir kursa baktığı zaman, kursa kayıtlı olup olmadığını görmelidir. Bunu yapmak için, courses toplama öğrencinin adına sorgulanan aldığında, biz students dizi zaten öğrencinin objectId içeriyorsa öğrenmek gerekir. Orada yalnızca students diziden öğrenci ObjectId almak için bir bulmak sorgusunun projeksiyonunda belirtmek için bir yolu var mı?

ben elemMatch operatörü, $ olabilir ama alt belgelerin bir dizi yönelikse olmadığını görmek için çalıştı. Anlaşma çerçevesini kullanabileceğimi anlıyorum, ancak bu durumda aşırı bir şekilde olacağı görünüyor. Toplama çerçevesi muhtemelen tek bir bulma sorgusu kadar hızlı olmayabilir. Kurs koleksiyonunu, iade edilen belgenin buna benzer bir formda olabilmesi için sorgulamanın bir yolu var mı?

{ 
     "_id" : ObjectId("51780fb5c9c41825e3e21fc4"), 
     "name" : "CS 101", 
     "students" : [ 
       ObjectId("51780f796ec4051a536015d0"), 
     ] 
} 

cevap

50

[ düzenleme düzenleme şu andaki son versiyonlarda mevcut olacaktır]

[Güncellendi] Ders adı ve öğrenci kimliğini geri almak için aşağıdaki yolu sorgulayabilirsiniz. ady kaydedildi.

db.student.find({}, 
{_id:0, name:1, students:{$elemMatch:{$eq:ObjectId("51780f796ec4051a536015cf")}}}) 

ve beklediğiniz geri alacak:

{ "name" : "CS 101", "students" : [ ObjectId("51780f796ec4051a536015cf") ] } 
{ "name" : "Literature" } 
{ "name" : "Physics", "students" : [ ObjectId("51780f796ec4051a536015cf") ] } 

[Orijinal Cevap] Bu, o anda ne yapmak istediğinizi yapmak mümkün değildir. Bu talihsiz bir şey çünkü öğrenci dizide bir nesne olarak saklandıysa bunu yapabileceksiniz. Aslında, sadece Nesne Kimliği() o daima Belirli bir derse kayıtlı öğrencilerin listesini görüntülemek istiyorsanız öğrencileri aramak için ihtiyaç (ilk Kimliği en listesini yukarı bakacak şekilde kullanıyor biraz şaşırdım sonra öğrenciler koleksiyonunda isimleri aramak - bir yerine iki sorgu!siz) bir örnek olarak (böyle ders dizide bir kimliği ve isim kaydetmek olsaydı

):

{ 
     "_id" : ObjectId("51780fb5c9c41825e3e21fc6"), 
     "name" : "Physics", 
     "students" : [ 
       {id: ObjectId("51780f796ec4051a536015cf"), name: "John"}, 
       {id: ObjectId("51780f796ec4051a536015d0"), name: "Sam"} 
     ] 
} 

Sorgunuzda sonra basitçe şöyle olacaktır:

db.course.find({ }, 
       { students : 
        { $elemMatch : 
         { id : ObjectId("51780f796ec4051a536015d0"), 
         name : "Sam" 
         } 
        } 
       } 
); 

o öğrenci olsaydı sadece CS 101'e kayıt yaptırırsınız:

{ "name" : "Literature" } 
{ "name" : "Physics" } 
{ 
    "name" : "CS 101", 
    "students" : [ 
     { 
      "id" : ObjectId("51780f796ec4051a536015cf"), 
      "name" : "John" 
     } 
    ] 
} 
+0

Basit dizileri ve alt-küme dizilerini sorgulayamamaya dair düşüncelerinizi doğruladığınız için teşekkür ederim. Şemalarımı yeniden değerlendirmem gerekecek. 10Gen'in bu sorunu ele almayı planlayıp planlamadığını biliyor musunuz? – shargors

+0

jira.mongodb.org adresinden bunun için bir Jira bileti bulamadım ve hiçbir şey bir bilet olmadan bir sürüm için planlanmış değil, bu yüzden yakında herhangi bir zamanda kesinlikle söyleyemem. –

+0

http://stackoverflow.com/questions/8145523/mongodb-find-by-multiple-array-items – Xerri

14

O $in operatör senin amaçları gayet hizmet verecek gibi görünüyor.

Bu (yalancı sorgusu) gibi bir şey yapabilirsiniz:. Alternatif

if (db.courses.find({"students" : {"$in" : [studentId]}, "course" : courseId }).count() > 0) { 
    // student is enrolled in class 
} 

, sen "course" : courseId maddesini kaldırmak ve öğrencinin kayıtlı olduğu tüm sınıflar kümesi geri alabilir

+0

Bu yaklaşımın problemi, derslerin toplanmasıyla ilgili bir belge döndürmesidir. Sadece ders için kayıt yaptıysanız, iyon. Öğrenci kayıtlı değilse, ikinci bir sorgu gerekli olacaktır. Bu verimli değil. – shargors

+0

İkinci sorgu öğrencinin nesne kimliğini almak mı? Ama bu zaten bilinmez (sonuçta, ilk sorguyu yapmak için kullanıyorsunuz). – xbonez

+0

Son hedef, kurs belgesini almak ve öğrencinin kayıt yaptığını gösteren bir işarete sahip olmaktır. Sağladığınız sorgu, yalnızca öğrenci kayıt yaptıysa kurs belgesini alacaktır. Öğrenci derse kayıt olmamışsa, kurs belgesini almak için başka bir sorguya ihtiyaç vardır. – shargors

İlgili konular