2016-07-08 11 views
1

Ich verwende ein Python-Skript, um eine MongoDB-Sammlung abzufragen. Die Sammlung enthält eingebettete Dokumente mit unterschiedlichen Strukturen.Workaround für preserveNullAndEmptyArrays in MongoDB 2.6

Ich versuche, ein Array in mehreren Dokumenten einfach "$ entspannen". Das Array befindet sich jedoch nicht in ALLEN Dokumenten.

Das bedeutet, dass nur die Dokumente zurückgegeben werden, die das Feld enthalten, die anderen werden ignoriert. Ich verwende PyMongo 2.6, so kann ich preserveNullAndEmptyArrays nicht verwenden, wie in der documentation erwähnt, weil es neu in MongoDB ist. 3.2

Gibt es eine Abhilfe zu diesem? Etwas nach dem Motto "Wenn der Feldweg existiert, entspannen Sie sich".

Die Struktur von Dokumenten und Code in Frage ist detailliert in diesem separaten aber related question Ich fragte früher.

PROBLEM:

Ich versuche, den Wert von $hostnames.name auf "$ Abroller". Da der Pfad jedoch nicht in allen Dokumenten vorhanden ist, führt dies zu mehreren ignorierten Dokumenten.

Struktur 1 Hostname gespeichert wie $ hostnames.name

{ 
    "_id" : "192.168.1.1", 
    "addresses" : { 
     "ipv4" : "192.168.1.1" 
    }, 
    "hostnames" : [ 
     { 
      "type" : "PTR", 
      "name" : "example.hostname.com" 
     } 
    ] 
} 

Struktur 2 Hostname gespeichert als Hostnamen $

{ 
    "_id" : "192.168.2.1", 
    "addresses" : { 
     "ipv4" : "192.168.2.1" 
    }, 
    "hostname" : "helloworld.com", 

} 

Script

cmp = db['computers'].aggregate([ 
    {"$project": { 
     "u_hostname": { 
      "$ifNull": [ 
       "$hostnames.name", 
       { "$map": { 
        "input": {"$literal": ["A"]}, 
        "as": "el", 
        "in": "$hostname" 
       }} 
      ] 
     }, 
     "_id": 0, 
     "u_ipv4": "$addresses.ipv4" 
    }}, 
    {"$unwind": "$u_hostname"} 
]) 

Ich vermisse alle Dokumente, die ein leeres Array für "Hostnamen" haben.

Hier ist die Struktur der Dokumente, die noch fehlen.

Struktur 3

{ 
    "_id" : "192.168.1.1", 
    "addresses" : { "ipv4" : "192.168.1.1" }, 
    "hostnames" : [], } 
} 

Antwort

1

Wir können immer noch alle Dokumente erhalten, wo das Array-Feld durch das Spiel mit dem $ifNull Operator fehlt und verwenden eine logische $cond ition Verarbeitung Wert auf die neu berechneten Feld zuweisen .

Die Bedingung hier ist $eq, die True zurückgibt, wenn das Feld [None] oder False ist, wenn der Bedingungsausdruck false ergibt.

cmp = db['computers'].aggregate(
    [ 
     {"$project":{ 
      "u_ipv4": "$addresses.ipv4", 
      "u_hostname": { 
       "$let": { 
        "vars": { 
         "hostnameName": { 
          "$cond": [ 
           {"$eq": ["$hostnames", []]}, 
           [None], 
           {"$ifNull": ["$hostnames.name", [None]]} 
          ] 
         }, 
         "hostname": {"$ifNull": ["$hostname", None]} 
        }, 
        "in": { 
         "$cond": [ 
          {"$eq": ["$$hostnameName", [None]]}, 
          {"$map": { 
           "input": {"$literal": [None]}, 
           "as": "el", 
           "in": "$$hostname" 
          }}, 
          "$$hostnameName" 
         ] 
        } 
       } 
      } 
     }},   
     { "$unwind": "$u_hostname" } 
    ] 
) 
Verwandte Themen