2012-01-07 12 views
17

Yaygın bir _id paylaşan iki MongoDB koleksiyonum var. Mongo kabuğunu kullanarak, diğer koleksiyonda eşleşen bir belgeye sahip olmayan bir koleksiyondaki tüm belgeleri bulmak istiyorum.MongoDB kabuk sorgusunda "toplamada değil koleksiyondaki veriler" al

Örnek: Çeşitli denedim

{ "_id" : ObjectId("4f08a767306b428fb9d8bb30"), "foo" : 3 } 
{ "_id" : ObjectId("4f08a769306b428fb9d8bb31"), "foo" : 4 } 

:

> db.Test.insert({ "_id" : ObjectId("4f08a75f306b428fb9d8bb2e"), "foo" : 1 }) 
> db.Test.insert({ "_id" : ObjectId("4f08a766306b428fb9d8bb2f"), "foo" : 2 }) 
> db.Test.insert({ "_id" : ObjectId("4f08a767306b428fb9d8bb30"), "foo" : 3 }) 
> db.Test.insert({ "_id" : ObjectId("4f08a769306b428fb9d8bb31"), "foo" : 4 }) 
> db.Test.find() 
{ "_id" : ObjectId("4f08a75f306b428fb9d8bb2e"), "foo" : 1 } 
{ "_id" : ObjectId("4f08a766306b428fb9d8bb2f"), "foo" : 2 } 
{ "_id" : ObjectId("4f08a767306b428fb9d8bb30"), "foo" : 3 } 
{ "_id" : ObjectId("4f08a769306b428fb9d8bb31"), "foo" : 4 } 
> db.Test2.insert({ "_id" : ObjectId("4f08a75f306b428fb9d8bb2e"), "bar" : 1 }); 
> db.Test2.insert({ "_id" : ObjectId("4f08a766306b428fb9d8bb2f"), "bar" : 2 }); 
> db.Test2.find() 
{ "_id" : ObjectId("4f08a75f306b428fb9d8bb2e"), "bar" : 1 } 
{ "_id" : ObjectId("4f08a766306b428fb9d8bb2f"), "bar" : 2 } 

Şimdi _ID en Test2 herhangi bir belge eşleşmeyen Testi iki dokümanları döndürür bazı sorgu satır istiyorum $ not, $ ne, $ veya $ in kombinasyonları ancak doğru kombinasyon ve sözdizimini alamıyor. Ayrıca, önce db.Test2.find({}, {"_id": 1})'un çalıştırılmasının bir değişkene kaydedilip kaydedilmediğini umuyorum (ki bu da ikinci bir sorguda kullanılır).

Güncelleştirme: Zachary'ın $ nin işaret eden yanıtı, sorunun ana bölümünü yanıtladı.

> db.Test.find({"_id": {"$nin": [ObjectId("4f08a75f306b428fb9d8bb2e"), ObjectId("4f08a766306b428fb9d8bb2f")]}}) 
{ "_id" : ObjectId("4f08a767306b428fb9d8bb30"), "foo" : 3 } 
{ "_id" : ObjectId("4f08a769306b428fb9d8bb31"), "foo" : 4 } 

Ama (ve bu kabul ölçeklenebilir ama bu durumda onun değil bir sorun nedeniyle yine de çalışıyor değil) hala kabuğunda birlikte iki sorgu birleştiremezsiniz: Örneğin, bu çalışır. Bu tabii ki ideal olanın altındaysa, hangi alabilirim en yakın: vals $ Nin için dizi girişi olarak doğrudan kullanılabilir, böylece find komutu sadece değerler döndürmek için bir yol

vals = db.Test2.find({}, {"_id": 1}).toArray() 
db.Test.find({"_id": {"$nin": [ObjectId(vals[0]._id), ObjectId(vals[1]._id)]}}) 

var mı?

cevap

12

A koleksiyonundan koleksiyonları B koleksiyonundan tekrar çekmemek için kaydetmeniz gerekir, ancak bunu $nin kullanarak yapabilirsiniz. MongoDB operatörlerinin tümü için Advanced Queries'a bakın. Bu yaklaşım ölçek olmayacağını

db.Test.find({"_id": {"$nin": [ObjectId("4f08a75f306b428fb9d8bb2e"), ObjectId("4f08a766306b428fb9d8bb2f")]}})

Not: Eğer böyle bir şey olmazdı verdi örneği kullanarak

Sonun sorgu. Ölçeklendiren bir çözüme gereksiniminiz varsa, _id koleksiyonunun diğer koleksiyonda olup olmadığını belirten A ve B koleksiyonlarında bir bayrak ayarlamalısınız ve bunun yerine bunu sorgulayabilirsiniz.

ikinci bölümü için Güncel:

ikinci bölümü imkansızdır. MongoDB, birleştirmeler veya tek bir sorguda koleksiyonlar arasında herhangi bir çapraz sorgulamayı desteklemez. Bir koleksiyondan sorgulama, sonuçları kaydetme ve ardından ikinci adımdan sorgulama, verileri daha önce de belirttiğim gibi satırlara yerleştirmedikçe tek seçeneğinizdir.

+1

Küçük şikayet: konsept doğru, fakat Test ve Test2'yi cevabınızda geriye doğru aldınız. "Şimdi, Test'teki herhangi bir belgenin Test2'deki herhangi bir belgeyle eşleşmediği iki belgeyi döndüren bazı sorgular veya sorgular istiyorum" –

+0

"> db.Test.find ({" _ id ": {" $ nin ": [ObjectId (" ": Nesne ("4f08a767306b428fb9d8bb30 "), "fan": 3} { "_ID": Nesne (" 4f08a769306b428fb9d8bb31"); 4f08a75f306b428fb9d8bb2e "), Nesne Kimliği (" 4f08a766306b428fb9d8bb2f _ID")]}}) ' ' {verir" , "foo": 4} ' –

+0

Teşekkürler, bu sorunun ana bölümünü yanıtladı, ancak bu ikinci kısmı da yanıtlamadan çok kullanışlı değil. Soruyu yansıtmak için güncelledim. – Raman

26

Bilgilerinizi yanıtlayın. Harita kullanıyorum().

Verilen bu:

> b1 = {i: 1} 
> db.b.save(b1) 
> db.b.save({i: 2}) 
> db.a.save({_id: b1._id}) 

Tek ihtiyacınız olan: İkinci koleksiyonu tüm belgeleri işaretleme, ben bir senaryo yaptık

{ "_id" : ObjectId("4f08c60d6b5e49fa3f6b46c1"), "i" : 2 } 
+0

Ahh, 'map', sweet! Bu mükemmel çalışıyor. Zachary'ın cevabını ve seninkini kabul edebilirdim. – Raman

+0

BTW, bir yerlerde belgelenmiş olası imleç yöntemleri nelerdir? Http://www.mongodb.org/display/DOCS/Queries+and+Cursors adresinde belirtilen 'map' işlevini ve http://www.mongodb.org/display/DOCS/Advanced+ adresini görmedim. Sorgular # AdvancedQueries-CursorMethods. – Raman

+2

'map', Mongo’dan çıkarılan dizide çalışan güzel, eski moda bir javascript standart kütüphane işlevidir. Mongo kabuğu keyfi JS'yi destekler. –

0

döndürür

> vals = db.a.find({}, {id: 1}).map(function(a){return a._id;}) 
> db.b.find({_id: {$nin: vals}}) 

o İlk koleksiyonda görünür. Daha sonra ikinci koleksiyon belgelerini işledim. Mongo'da Aşağıdaki kod görünüyor 3.2 olarak hiçbir iz

db.secondCollection.find({"firstCollectionField":{$exists:false}}) 
15

sahiptir ikinci koleksiyonu bu https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/#use-lookup-with-an-array örnek dayalı

db.collectionb.aggregate([ 
    { 
     $lookup: 
     { 
      from: "collectiona", 
      localField: "collectionb_fk", 
      foreignField: "collectiona_fk", 
      as: "matched_docs" 
     } 
    }, 
    { 
     $match: { "matched_docs": { $eq: [] } } 
    } 
]); 

çalışmak

var first = db.firstCollection.aggregate([ {'$unwind':'$secondCollectionField'} ]) 

while (first.hasNext()){ var doc = first.next(); db.secondCollection.update({_id:doc.secondCollectionField} ,{$set:{firstCollectionField:doc._id}}); } 

... süreç

0

db.bar.find ({_ id: {$ nin: db.foo.find ({}, {_ id: 1}) .ArArray()}})

+0

Bu soru daha önce cevaplandırıldı. Lütfen cevabınız hakkında daha fazla bilgi ekleyin veya silin –