MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Aggregazione MongoDb Manipolazione dei dati - Oggetti in array

Interroga

  • è un aggiornamento di aggregazione anche se la pipeline non ci consente di utilizzare fasi come la ricerca di gruppo ecc. Che qui viene utilizzata. (puoi usare $out e sostituisci la raccolta dopo o $merge per sostituire documenti (simile all'aggiornamento))

  • prima mappa

    • per ogni tratto (membro del documento dei tratti), viene inserito nell'array
      [["trait_type": "type"] ["value": "Male"] ["display_type": null] ...]
    • riduci su quell'array per costruire da esso solo 1 documento
      {"type" "type","value" :"Male"} (fa anche quello minuscolo e "_")
  • Ora i tratti sono simili

    "traits": [
      {
        "type": "type",
        "value": "Male"
      },
      {
        "type": "accessory",
        "value": "Mohawk"
      },
      {
        "type": "accessory",
        "value": "Earring"
      },
      {
        "type": "accessory",
        "value": "Frown"
      }
    ]
    
  • ricerca con la collezione fittizia [{}] (lo facciamo per creare un gruppo all'interno di quell'array) è come un trucco che ci permette di usare gli operatori di stage all'interno di 1 documento

    • La pipeline di ricerca si svolge e raggruppa per tipo
    "traits": [
      {
        "values": [
          "Mohawk",
          "Earring",
          "Frown"
        ],
        "type": "accessory"
      },
      {
        "values": [
          "Male"
        ],
        "type": "type"
      }
    ]
    
    • quindi è una radice sostitutiva per prendere il valore di tipo, renderlo il nome del campo e i valori come valore (if size=1 removes the array)
  • Dopo la ricerca abbiamo

    "traits": [
      {
        "accessory": [
          "Mohawk",
          "Earring",
          "Frown"
        ]
      },
      {
        "type": "Male"
      }
    ]
    
  • quindi tutto ciò che dobbiamo fare è ridurre quei tratti e unire gli oggetti (le chiavi sono comunque uniche perché siamo raggruppate per esse)

  • e otteniamo l'output previsto (almeno penso che sia ok)

Testare il codice qui

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"
      }
    }
  }
])