2016-04-14 18 views
2

Ich versuche, Mongo Aggregation Framework zu verwenden, um Schnittmenge zwischen einem Array in meinem Dokument UND einem anderen benutzerdefinierten Array herauszufinden. Ich bekomme kein korrektes Ergebnis und meine Vermutung ist wegen der Tatsache, dass ich Array innerhalb eines Arrays habe.Kreuzung von Filialdokumentarray mit benutzerdefiniertem Array zurückgeben?

Hier ist mein Datensatz.

Meine Dokumente:

{ 
    "_id" : 1, 
    "pendingEntries" : [ 
     { 
      "entryID" : ObjectId("5701b4c3c6b126083332e65f"), 
      "tags" : [ 
       { 
        "tagKey" : "owner", 
        "tagValue" : "john" 
       }, 
       { 
        "tagKey" : "ErrorCode", 
        "tagValue" : "7001" 
       }, 
       { 
        "tagKey" : "ErrorDescription", 
        "tagValue" : "error123" 
       } 
      ], 
      "entryTime" : ISODate("2016-04-04T00:26:43.167Z") 
     } 
    ] 
}, 

/* 1 */ 
{ 
    "_id" : 2, 
    "pendingEntries" : [ 
     { 
      "entryID" : ObjectId("5701b4c3c6b126083332e65d"), 
      "tags" : [ 
       { 
        "tagKey" : "owner", 
        "tagValue" : "peter" 
       }, 
       { 
        "tagKey" : "ErrorCode", 
        "tagValue" : "6001" 
       }, 
       { 
        "tagKey" : "JIRA", 
        "tagValue" : "Oabc-123" 
       } 
      ], 
      "entryTime" : ISODate("2016-04-04T00:26:43.167Z") 
     } 
    ] 
}, 

/* 2 */ 
{ 
    "_id" : 3, 
    "pendingEntries" : [ 
     { 
      "entryID" : ObjectId("5701b4c3c6b126083332e65c"), 
      "tags" : [ 
       { 
        "tagKey" : "owner", 
        "tagValue" : "abc" 
       }, 
       { 
        "tagKey" : "ErrorCode", 
        "tagValue" : "6001" 
       }, 
       { 
        "tagKey" : "JIRA", 
        "tagValue" : "abc-123" 
       } 
      ], 
      "entryTime" : ISODate("2016-04-04T00:26:43.167Z") 
     } 
    ] 
} 

Meine Suche:

db.entrylike.aggregate(
    [ 
    { $project: { "pendingEntries.entryID": 1, "common": { $setIntersection: [ "$pendingEntries.tags", [{ "tagKey" : "ErrorCode", "tagValue" : "7001" }] ] } } } 
    ] 
) 

Ergebnis:

{ 
    "result" : [ 
     { 
      "_id" : 1, 
      "pendingEntries" : [ 
       { 
        "entryID" : ObjectId("5701b4c3c6b126083332e65f") 
       } 
      ], 
      "common" : [] 
     }, 
     { 
      "_id" : 2, 
      "pendingEntries" : [ 
       { 
        "entryID" : ObjectId("5701b4c3c6b126083332e65d") 
       } 
      ], 
      "common" : [] 
     }, 
     { 
      "_id" : 3, 
      "pendingEntries" : [ 
       { 
        "entryID" : ObjectId("5701b4c3c6b126083332e65c") 
       } 
      ], 
      "common" : [] 
     } 
    ], 
    "ok" : 1 
} 

Ich bin nicht der erste gemeinsame Feld leer zu sein erwartet. Kann mir jemand sagen, was ich falsch mache? Oder irgendwelche Arbeitsumgebungen, die ich nehmen kann.

Ich benutze mongodb 3.0.8. Ich bin mir der Tatsache bewusst, dass Mongodb 3.2 einige Features anbieten kann, die meine Bedürfnisse erfüllen, aber ein Upgrade von 3.2 ist nicht in Vorbereitung, und ich versuche, dies möglichst mit Mongo3.0 zu lösen.

Mein Ziel ist es entweder Tags Array durch die gemeinsamen Elemente aus der benutzerdefinierten Liste zu ersetzen oder ein neues Feld mit gemeinsamen Elementen hinzuzufügen. Ich versuche es zu dem späteren in meinem Beispiel.

Antwort

2

Der Grund dafür, dass das allgemeine Feld leer ist, liegt darin, dass Ihr Array "pendingEntries" und Ihr benutzerdefiniertes Array kein Element gemeinsam haben. Was Sie wirklich wollen, ist ein Array zurückzugeben, das die Elemente enthält, die in Ihrem Array "Tags" und in Ihrem benutzerdefinierten Array erscheinen. Dazu können Sie einfach den Operator $map verwenden und den Operator $setIntersection auf jedes Unterdokument "Tags" im Array "pendingEntries" anwenden.

db.entrylike.aggregate([ 
    { "$project": { 
     "common": { 
      "$map": { 
       "input": "$pendingEntries", 
       "as": "p", 
       "in": { 
        "entryID": "$$p.entryID", 
        "tags": { 
         "$setIntersection": [ 
          "$$p.tags", 
          { "$literal": [ 
           { 
            "tagKey" : "ErrorCode", 
            "tagValue" : "7001" 
           } 
          ]} 
         ] 
        } 
       } 
      } 
     } 
    }} 
]) 

Welche zurück:

{ 
    "_id" : 1, 
    "common" : [ 
     { 
      "entryID" : ObjectId("5701b4c3c6b126083332e65f"), 
      "tags" : [ 
       { 
        "tagKey" : "ErrorCode", 
        "tagValue" : "7001" 
       } 
      ] 
     } 
    ] 
} 
{ 
    "_id" : 2, 
    "common" : [ 
     { 
      "entryID" : ObjectId("5701b4c3c6b126083332e65d"), 
      "tags" : [ ] 
     } 
    ] 
} 
{ 
    "_id" : 3, 
    "common" : [ 
     { 
      "entryID" : ObjectId("5701b4c3c6b126083332e65c"), 
      "tags" : [ ] 
     } 
    ] 
} 
+1

Der '$ literal' sollte in diesem Zusammenhang nicht erforderlich, da es völlig in Ordnung ist, die einzige Element-Array direkt in' $ setIntersection' einfach notate. Bemerkenswert ist auch, dass '$ setIntersection' nur dann funktioniert, wenn die Elemente in der" exact "Reihenfolge stehen, und ein' [{"tagValue": "7001", "tagKey": "ErrorCode"}] 'Notation würde also nicht "sei eine Übereinstimmung, bei der entweder der Vergleich oder die gespeicherten Daten nicht in der Reihenfolge der Schlüssel lagen. Der Hauptpunkt ist natürlich, $ map zu verwenden, um auf die Elemente zuzugreifen und die geänderte Form zurückzugeben. Was ist wie gesagt. –

+0

@NeilLunn Ich auch, dass '$ literal' nicht benötigt wurde, aber ohne' $ literal', die Abfrage fehlgeschlagen mit * "FieldPath 'ErrorCode' beginnt nicht mit $" * – styvane

+0

Sie müssen einen Tippfehler haben. 'db.collection.aggregate ({" $ project ": {" a ": {" $ setIntersection ": [[" a "," b "], [" b "]]}}}) ist einfach reproduzierbar Fall. –

Verwandte Themen