MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

MongoDb Aggregation Datenmanipulation – Objekte zu Arrays

Abfrage

  • Es ist ein Aggregationsupdate, auch wenn die Pipeline es uns nicht erlaubt, Stufen wie die Gruppensuche usw. zu verwenden, die hier verwendet werden. (Sie können $out verwenden und ersetzen Sie die Sammlung nach oder $merge zum Ersetzen von Dokumenten (ähnlich wie Update))

  • erste Karte

    • Für jedes Merkmal (Dokumentmitglied von Merkmalen) wird es in ein Array aufgenommen
      [["trait_type": "type"] ["value": "Male"] ["display_type": null] ...]
    • Reduzieren Sie dieses Array, um daraus nur 1 Dokument zu erstellen
      {"type" "type","value" :"Male"} (gilt auch für Kleinbuchstaben und "_")
  • Now traits like

    "traits": [
      {
        "type": "type",
        "value": "Male"
      },
      {
        "type": "accessory",
        "value": "Mohawk"
      },
      {
        "type": "accessory",
        "value": "Earring"
      },
      {
        "type": "accessory",
        "value": "Frown"
      }
    ]
    
  • Suche mit der Dummy-Sammlung [{}] (Wir machen das, um eine Gruppe innerhalb dieses Arrays zu erstellen) Es ist wie ein Trick, der es uns erlaubt, Stage-Operatoren innerhalb eines Dokuments zu verwenden

    • Lookup-Pipeline wird abgewickelt und nach Typ gruppiert
    "traits": [
      {
        "values": [
          "Mohawk",
          "Earring",
          "Frown"
        ],
        "type": "accessory"
      },
      {
        "values": [
          "Male"
        ],
        "type": "type"
      }
    ]
    
    • dann ist es eine Ersetzungswurzel, um den Wert von type zu nehmen, ihn zum Feldnamen zu machen und die Werte als Wert (if size=1 removes the array)
  • Nach der Suche haben wir

    "traits": [
      {
        "accessory": [
          "Mohawk",
          "Earring",
          "Frown"
        ]
      },
      {
        "type": "Male"
      }
    ]
    
  • Alles, was wir tun müssen, ist, diese Eigenschaften zu reduzieren und die Objekte zusammenzuführen (Schlüssel sind sowieso einzigartig, weil wir nach ihnen gruppiert haben)

  • und wir bekommen die erwartete Ausgabe (zumindest denke ich, dass es ok ist)

Code hier testen

db.collection.aggregate([
  {
    "$set": {
      "traits": {
        "$map": {
          "input": "$traits",
          "as": "t",
          "in": {
            "$reduce": {
              "input": {
                "$map": {
                  "input": {
                    "$objectToArray": "$$t"
                  },
                  "as": "m",
                  "in": [
                    "$$m.k",
                    "$$m.v"
                  ]
                }
              },
              "initialValue": {},
              "in": {
                "$let": {
                  "vars": {
                    "type_value": "$$value",
                    "ta": "$$this"
                  },
                  "in": {
                    "$let": {
                      "vars": {
                        "key": {
                          "$arrayElemAt": [
                            "$$ta",
                            0
                          ]
                        },
                        "value": {
                          "$arrayElemAt": [
                            "$$ta",
                            1
                          ]
                        }
                      },
                      "in": {
                        "$switch": {
                          "branches": [
                            {
                              "case": {
                                "$eq": [
                                  "$$key",
                                  "value"
                                ]
                              },
                              "then": {
                                "$mergeObjects": [
                                  "$$type_value",
                                  {
                                    "value": "$$value"
                                  }
                                ]
                              }
                            },
                            {
                              "case": {
                                "$eq": [
                                  "$$key",
                                  "trait_type"
                                ]
                              },
                              "then": {
                                "$mergeObjects": [
                                  "$$type_value",
                                  {
                                    "type": {
                                      "$replaceAll": {
                                        "input": {
                                          "$toLower": "$$value"
                                        },
                                        "find": " ",
                                        "replacement": "_"
                                      }
                                    }
                                  }
                                ]
                              }
                            }
                          ],
                          "default": "$$type_value"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  {
    "$lookup": {
      "from": "dummy",
      "let": {
        "traits": "$traits"
      },
      "pipeline": [
        {
          "$set": {
            "traits": "$$traits"
          }
        },
        {
          "$unwind": {
            "path": "$traits"
          }
        },
        {
          "$replaceRoot": {
            "newRoot": "$traits"
          }
        },
        {
          "$group": {
            "_id": "$type",
            "values": {
              "$push": "$value"
            }
          }
        },
        {
          "$set": {
            "type": "$_id"
          }
        },
        {
          "$project": {
            "_id": 0
          }
        },
        {
          "$replaceRoot": {
            "newRoot": {
              "$cond": [
                {
                  "$eq": [
                    {
                      "$size": "$values"
                    },
                    1
                  ]
                },
                {
                  "$arrayToObject": {
                    "$let": {
                      "vars": {
                        "pair": [
                          [
                            "$type",
                            {
                              "$arrayElemAt": [
                                "$values",
                                0
                              ]
                            }
                          ]
                        ]
                      },
                      "in": "$$pair"
                    }
                  }
                },
                {
                  "$arrayToObject": {
                    "$let": {
                      "vars": {
                        "pair": [
                          [
                            "$type",
                            "$values"
                          ]
                        ]
                      },
                      "in": "$$pair"
                    }
                  }
                }
              ]
            }
          }
        }
      ],
      "as": "traits"
    }
  },
  {
    "$set": {
      "traits": {
        "$mergeObjects": "$traits"
      }
    }
  }
])