2017-10-11 65 views
5

İki koleksiyona katılmak ($ ​​lookup) için bir mongodb toplama sorgusu kullanmaya çalışıyorum ve daha sonra birleşik dizideki tüm benzersiz değerleri sayın. * Not: MetaDataMap dizisinde hangi alanların (anahtarların) olduğunu bilmiyorum. Harita'da bulunabilecek veya bulunmayabilecek alanlar saymak ya da içermemek istemiyorum. Bu yüzden toplama sorgusu böyle görünüyor.Mongodb aggregation boru hattı boyutu ve hızı sorunu

Yani benim iki koleksiyon şuna benzer: events-

{ 
"_id" : "1", 
"name" : "event1", 
"objectsIds" : [ "1", "2", "3" ], 
} 

{ 
"_id" : "1", 
"name" : "object1", 
"metaDataMap" : { 
        "SOURCE" : ["ABC", "DEF"], 
        "DESTINATION" : ["XYZ", "PDQ"], 
        "TYPE" : [] 
       } 
}, 
{ 
"_id" : "2", 
"name" : "object2", 
"metaDataMap" : { 
        "SOURCE" : ["RST", "LNE"], 
        "TYPE" : ["text"] 
       } 
}, 
{ 
"_id" : "3", 
"name" : "object3", 
"metaDataMap" : { 
        "SOURCE" : ["NOP"], 
        "DESTINATION" : ["PHI", "NYC"], 
        "TYPE" : ["video"] 
       } 
} 

Nesneleri Benim sonuçları ne var bugüne kadar bu

{ 
_id:"SOURCE", count:5 
_id:"DESTINATION", count: 4 
_id:"TYPE", count: 2 
} 

şunlardır:

db.events.aggregate([ 
{$match: {"_id" : id}} 

,{$lookup: {"from" : "objects", 
     "localField" : "objectsIds", 
     "foreignField" : "_id", 
     "as" : "objectResults"}} 

,{$unwind: "$objectResults"} //Line 1 
,{$project: {x: "$objectResults.metaDataMap"}} //Line 2 


,{$unwind: "$x"} 
,{$project: {"_id":0}} 

,{$project: {x: {$objectToArray: "$x"}}} 
,{$unwind: "$x"} 

,{$group: {_id: "$x.k", tmp: {$push: "$x.v"}}} 

,{$addFields: {tmp: {$reduce:{ 
input: "$tmp", 
initialValue:[], 
in:{$concatArrays: [ "$$value", "$$this"]} 
    }} 
}} 

,{$unwind: "$tmp"} 
,{$group: {_id: "$_id", uniqueVals: {$addToSet: "$tmp"}}} 

,{$addFields: {count: {"$size":"$uniqueVals"}}} 
,{$project: {_id: "$_id", count: "$count"}} 
]); 

Sorunum, satır 1 & işaretliydi. Yukarıdaki işler ancak metaDataMap dizi alanlarında (objectsResults.metaDataMap) 25.000 değer için yaklaşık 50 saniye sürüyor. Örneğin, nesne 1 metaDataMap SOURCE dizisinde 25.000 değere sahip. Bu yavaşlama yolu. bunu yapmak için Benim diğer hızlı bir yolu olan 1 & 2 satırını değiştirmekti: (3 saniyenin altında) Bu şekilde hızlıdır

,{$project: {x: "$objectResults.metaDataMap"}} //Line 1 
,{$unwind: "$x"} //Line 2 

ama sadece ~ 10,000 öğeleri veya daha az olan veri kümeleri üzerinde çalıştırılabilir. Herhangi bir şey daha yüksek ve "maksimum belge boyutunu aşıyor" diyen bir hata alıyorum.

Lütfen yardım edin!

+0

"Çeşitli dizilerde 25.000 öğe" etrafında biraz daha fazla açıklama ekleyebilir misiniz? –

+1

Sadece bir düşünce. "MetaDataMap" yapınızı "metaDataMap" olarak değiştirmeyi deneyebilirsiniz: ["k": {"SOURCE", "v": ["ABC", "DEF"]} ...] 've bir' ekleme $ lookup'dan sonra $ map' sahne. "{" $ Project "gibi bir şey: {" data ": {" $ map ": {" input ":" $ objectResults.metaDataMap "," as ":" resultom "," in ":" {"$ map": {"input": "$$ resultom", "as": "resultim", "in": {"k": "$$ resultim.k", "v": {\t "$ boyut": \t "$ $ resultim.v "}}}}}}}}. Bu şekilde, boyutu alabileceğinizi ve gevşemenin daha hızlı olması gerektiğine inanıyorum. – Veeram

+0

Ama boyut ile ayrı bir sayı elde edemem. Ben mi V değerlerini kaldırmalıyım. – Deckard

cevap

0

Bir parent_id alanı kapsayacak şekilde object koleksiyonu üzerinde şema tasarımı değiştirmek mümkün iseniz, derhal boru hattının ilk 4 aşamalarını (ilk $match, $lookup, $unwind ve $project) kaldırabilirsiniz. Bu, Line 1 ve Line 2 kaygılarını ortadan kaldıracaktır.

{ 
    "_id": "1", 
    "name": "object1", 
    "metaDataMap": { 
    "SOURCE": [ 
     "ABC", 
     "DEF" 
    ], 
    "DESTINATION": [ 
     "XYZ", 
     "PDQ" 
    ], 
    "TYPE": [ ] 
    }, 
    "parent_id": "1" 
} 

Böylece pahalı $lookup ve $unwind gerekmez: gibi

Örneğin, object koleksiyonunda bir belge görünürdü. İlk 4 aşamaları daha sonra değiştirilebilir:

db.objects.aggregate([ 
    {$match: {parent_id: id}} 
    ,{$project: {metaDataMap: {$filter: {input: {$objectToArray: '$metaDataMap'}, cond: {$ne: [[], '$$this.v']}}}}} 
    ,{$unwind: '$metaDataMap'} 
    ,{$unwind: '$metaDataMap.v'} 
    ,{$group: {_id: '$metaDataMap.k', val: {$addToSet: '$metaDataMap.v'}}} 
    ,{$project: {count: {$size: '$val'}}} 
]) 

çıktısı verir:

{ "_id": "TYPE", "count": 2 } 
{ "_id": "DESTINATION", "count": 4 } 
{ "_id": "SOURCE", "count": 5 } 
Bu fikrin temelinde

{$match: {parent_id: id}} 

, ben sonuçlandı boru hattının daha fazla optimizasyon yaptık