2017-07-07 6 views
1

Ich habe ein Array A im Speicher zur Laufzeit erstellt und ein anderes Array B in einer Mongo-Datenbank gespeichert. Wie kann ich effizient alle Elemente von A erhalten, die nicht in B sind?Vergleiche Arrays und gebe den Unterschied zurück

Sie können davon ausgehen, dass das in mongodb gespeicherte Array mehrere Größenordnungen größer als das zur Laufzeit erstellte Array ist. Aus diesem Grund denke ich, dass das Erlangen des vollständigen Arrays aus Mongo und Berechnen des Ergebnisses nicht effizient wäre Ich habe keine Abfrageoperation in Mongo gefunden, mit der ich das gewünschte Ergebnis berechnen kann.

Beachten Sie, dass der $nin Operator tut das Gegenteil von dem, was ich will, das heißt, ruft es die Elemente von B, die nicht in A. sind

Beispiel:

Array A, in meinem appliction zur Laufzeit erstellt , ist [2, 3, 4].

Array B, gespeichert in Mongodb, ist [1, 3, 5, 6, 7, 10]. Das Ergebnis, das ich erwarte, ist [2, 4].

Antwort

3

Die einzigen Dinge, die das Dokument als Antwort "modifizieren" sind .aggregate() und .mapReduce(), wobei ersteres die bessere Option ist.

In diesem Fall fragen Sie nach $setDifference, die die "Sätze" vergleicht und die "Differenz" zwischen den beiden zurückgibt.

So ein Dokument mit Ihrem Array darstellen:

db.collection.insert({ "b": [1, 3, 5, 6, 7, 10] }) 

die Aggregation Run:

db.collection.aggregate([{ "$project": { "c": { "$setDifference": [ [2,3,4], "$b" ] } } }]) 

Welche zurück:

{ "_id" : ObjectId("596005eace45be96e2cb221b"), "c" : [ 2, 4 ] } 

Wenn Sie nicht wollen, "Sets" und stattdessen Möchten Sie ein Array wie [2,3,4,4] liefern dann können Sie mit $filter undvergleichenstatt, wenn Sie MongoDB 3.4 zumindest:

db.collection.aggregate([ 
    { "$project": { 
    "c": { 
     "$filter": { 
     "input": [2,3,4,4], 
     "as": "a", 
     "cond": { 
      "$not": { "$in": [ "$$a", "$b" ] } 
     } 
     } 
    } 
    }} 
]) 

Oder mit $filter und $anyElementTrue in früheren Versionen:

db.collection.aggregate([ 
    { "$project": { 
    "c": { 
     "$filter": { 
     "input": [2,3,4,4], 
     "as": "a", 
     "cond": { 
      "$not": { 
      "$anyElementTrue": { 
       "$map": { 
       "input": "$b", 
       "as": "b", 
       "in": { 
        "$eq": [ "$$a", "$$b" ]  
       } 
       }  
      } 
      } 
     }  
     } 
    }  
    }} 
]) 

Wo beide zurückkehren würde:

{ "_id" : ObjectId("596005eace45be96e2cb221b"), "c" : [ 2, 4, 4 ] } 

was natürlich "kein Satz", da die 4 als Eingabe "zweimal" bereitgestellt wurde und daher auch "doppelt" zurückgegeben wird.

Verwandte Themen