2016-06-20 10 views
1

ich eine Sammlung haben mit Dokumenten gefüllt somehting wie folgt aussehen:Unwind in mongodb Aggregat mit mehreren verschachtelten, aber möglicherweise leer, Arrays

{ 
    _id: <id> 
    arrayOne: [{name: <string>, listings: [<string>, <string>, ...]}], 
    arrayTwo: [{name: <string>, listings: [<string>, <string>, ...]}] 
} 

Was ich brauche, ist ein flaches Array in dem jeder String in Angebote von beiden arrayOne und arrayTwo ist ohne Duplikate dargestellt, so dass ich dies tun:

aggregate([ 
    { $match: { _id: <id>} }, 
    { $unwind: '$arrayOne' }, 
    { $unwind: '$arrayOne.listings' }, 
    { $unwind: '$arrayTwo' }, 
    { $unwind: '$arrayTwo.listings' }, 
    { $group : { _id : '$_id', setOne: { $addToSet: '$arrayOne.listings'}, setTwo: {$addToSet: '$arrayTwo.listings'} } }, 
    { $project: {unique_appearances: {$setUnion: ['$setOne', '$setTwo']}}} 
]); 

Das funktioniert ganz gut, bis wir dies auf einem Dokument laufen, wo arrayOne oder arrayTwo leer.

Heute löse ich es durch einen falschen Wert Hinzufügen (vor Abwickeln), die ich in der letzten Zeile herausfiltern, wie folgt aus:

aggregate([ 
    { $match: { _id: <id>} }, 
    { $project: { 
     _id: '$_id', 
     arrayOne: { $cond : [{$gt: ['$arrayOne', []]}, '$arrayOne', [{listings: ['cheezeburglars']}]] }, 
     arrayTwo: { $cond: [{$gt: ['$arrayTwo', []]}, '$arrayTwo', [{listings: ['cheezeburglars']}]] } 
    } 
    }, 
    { $unwind: '$arrayOne' }, 
    { $unwind: '$arrayOne.listings' }, 
    { $unwind: '$arrayTwo' }, 
    { $unwind: '$arrayTwo.listings' }, 
    { $group : { _id : '$_id', setOne: { $addToSet: '$arrayOne.listings'}, setTwo: {$addToSet: '$arrayTwo.listings'} } }, 
    { $project: { 
    unique_appearances: { 
     $setDifference: [{$setUnion: ['$setOne: ', '$setTwo']}, ['cheezeburglars']] 
    } 
    }} 
]); 

Dies funktioniert, aber ich fühle, dass meine Lösung ist ein bisschen hacky. Gibt es einen besseren Weg, dies zu lösen?

Antwort

3

Sie können diese 3.2+ in den entsprechenden $unwind Stufen der preserveNullAndEmptyArrays: true Option, indem in MongoDB tun:

aggregate([ 
    { $match: { _id: <id>} }, 
    { $unwind: { path: '$arrayOne', preserveNullAndEmptyArrays: true } }, 
    { $unwind: '$arrayOne.listings' }, 
    { $unwind: { path: '$arrayTwo', preserveNullAndEmptyArrays: true } }, 
    { $unwind: '$arrayTwo.listings' }, 
    { $group : { _id : '$_id', setOne: { $addToSet: '$arrayOne.listings'}, setTwo: {$addToSet: '$arrayTwo.listings'} } }, 
    { $project: {unique_appearances: {$setUnion: ['$setOne', '$setTwo']}}} 
]); 

diese Option Einstellung wird die $unwind verursachen noch das Dokument in der Ausgabe enthalten zu sein, auch wenn das Feld ist leer (oder null oder fehlt).

+0

das ist nett man! Vielen Dank – profesor79