sql >> Databáze >  >> NoSQL >> MongoDB

Zploštění schématu mongoDB

Nová odpověď

Vytiskněte data

db.test.find().forEach(doc => {
  doc.details = doc.details.map( detail => {
    Object.keys(detail).filter( k => k !== "_id" ).forEach( k => {
      detail[k].forEach( item => {
        Object.keys(item).filter(i => i !== "_id" ).forEach( inner => {
          detail[k + inner.charAt(0).toUpperCase() + inner.substr(1)]
            = item[inner];
        })
      });
      delete detail[k];
    });
    return detail;
  });
  printjson(doc);
});

Aktualizujte data

db.test.find().forEach(doc => {
  doc.details = doc.details.map( detail => {
    Object.keys(detail).filter( k => k !== "_id" ).forEach( k => {
      detail[k].forEach( item => {
        Object.keys(item).filter(i => i !== "_id" ).forEach( inner => {
          detail[k + inner.charAt(0).toUpperCase() + inner.substr(1)]
            = item[inner];
        })
      });
      delete detail[k];
    });
    return detail;
  });

  ops = [
    ...ops,
    { "updateOne": {
      "filter": { "_id": doc._id },
      "update": { "$set": { "doc.details": doc.details } }
    }}
  ];

  if ( ops.length >= 500 ) {
    db.test.bulkWrite(ops);
    ops = [];
  }
});

if ( ops.length > 0 ) {
  db.test.bulkWrite(ops);
  ops = [];
}

Formulář výstupu

{
    "_id" : ObjectId("58e574a768afb6085ec3a388"),
    "details" : [
        {
          "_id" : ObjectId("58e55f0f68afb6085ec3a2cc"),
          "aUnit" : "08",
          "aSize" : "5",
          "aPos" : "Far",
          "bUnit" : "08",
          "bSize" : "5",
          "bPos" : "Far",
          "cUnit" : "08",
          "cSize" : "3",
          "cPos" : "Far",
          "dUnit" : "08",
          "dSize" : "5",
          "dPos" : "Far"
        }
    ]
}

Původní data

{
    "_id" : ObjectId("58e574a768afb6085ec3a388"),
    "tests" : [
      {
        "_id" : ObjectId("58e542fb68afb6085ec3a1d2"),
        "details" : [
          {
            "a" : [
              {
                "unit" : "08",
                "size" : "5",
                "pos" : "Far",
                "_id" : ObjectId("58e542fb68afb6085ec3a1d6")
              }
            ]
          },
          {
            "b" : [
              {
                "pos" : "Drive Side Far",
                "size" : "5",
                "unit" : "08",
                "_id" : ObjectId("58e542fb68afb6085ec3a1d3")
              }
            ]
          },
          {
            "c" : [
              {
                "pos" : "Far",
                "size" : "3",
                "unit" : "08",
                "_id" : ObjectId("58e542fb68afb6085ec3a1d4")
              }
            ]
          },
          {
            "d" : [
              {
                "pos" : "Far",
                "size" : "5",
                "unit" : "08",
                "_id" : ObjectId("58e542fb68afb6085ec3a1d5")
              }
            ]
          }
        ]
      }
    ]
}

Původní odpověď

Pokud se snažíte „aktualizovat“ svá data, pak je to mnohem složitější, než to, o co se pokoušíte. Máte několik polí a musíte prvky pole skutečně „procházet“, než se k nim pokoušet přímo přistupovat.

Zde je jen příklad, jak „vytisknout“ „zploštělá“ data:

db.test.find().forEach(doc => {
  doc.tests = doc.tests.map( test => {
    test.details.forEach( detail => {
      Object.keys(detail).forEach( key => {
        detail[key].forEach( item => {
          Object.keys(item).forEach( inner => {
            if ( inner !== '_id' ) {
              test[key + inner.charAt(0).toUpperCase() + inner.substr(1)]
                = item[inner];
            }
          });
        });
      });
    });
    delete test.details;
    return test;
  });
  printjson(doc);
})

Což, jak věřím, dává strukturu, kterou hledáte:

{
    "_id" : ObjectId("58e574a768afb6085ec3a388"),
    "tests" : [
        {
            "_id" : ObjectId("58e542fb68afb6085ec3a1d2"),
            "aUnit" : "08",
            "aSize" : "5",
            "aPos" : "Far",
            "bPos" : "Drive Side Far",
            "bSize" : "5",
            "bUnit" : "08",
            "cPos" : "Far",
            "cSize" : "3",
            "cUnit" : "08",
            "dPos" : "Far",
            "dSize" : "5",
            "dUnit" : "08"
        }
    ]

}

Nyní neberu v úvahu žádnou možnost, že uvnitř vašich "details" seřaďte dokumenty pomocí klíčů jako "a" atd. se mohou objevit vícekrát. Takže uvažuji, že uvnitř je vždy pouze 1 dokument, který má "a" nebo "b" atd. a poslední nalezená hodnota odpovídající tomuto klíči je vždy přiřazena při přidávání nových klíčů na nejvyšší úroveň "details" dokumenty.

Pokud se vaše skutečné případy liší, budete muset upravit různé .forEach() smyčky uvnitř tam také použít "index" jako parametr a zahrnout tuto hodnotu indexu jako součást názvu klíče. tj.:

"a0Unit": "08",
"a0Size": "05",
"a1Unit": "09",
"a1Size": "06"

Ale to je detail, který budete muset v případě potřeby vyřešit, protože by se lišil od toho, jak jsou data prezentována v otázce.

Pokud se to však dokonale hodí pro to, na co chcete aktualizovat, pak jednoduše spusťte smyčku pomocí .bulkWrite() příkazy spouštěné v pravidelných intervalech:

let ops = [];

db.test.find().forEach(doc => {
  doc.tests = doc.tests.map( test => {
    test.details.forEach( detail => {
      Object.keys(detail).forEach( key => {
        detail[key].forEach( item => {
          Object.keys(item).forEach( inner => {
            if ( inner !== '_id' ) {
              test[key + inner.charAt(0).toUpperCase() + inner.substr(1)]
                = item[inner];
            }
          });
        });
      });
    });
    delete test.details;
    return test;
  });

  ops = [
    ...ops,
    { "updateOne": {
      "filter": { "_id": doc._id },
      "update": { "$set": { "tests": doc.tests } }
    }}
  ];

  if ( ops.length >= 500 ) {
    db.test.bulkWrite(ops);
    ops = [];
  }
});

if ( ops.length > 0 ) {
  db.test.bulkWrite(ops);
  ops = [];
}

Objevuje se také z _id pole přítomná v každém členském dokumentu pole, který používáte mongoose. Takže ať děláte cokoli, nezkoušejte spustit kód pomocí samotného mongoose. Je to „jednorázová“ hromadná aktualizace vašich dat a měla by být spouštěna přímo z prostředí. Pak samozřejmě budete muset upravit své schéma tak, aby vyhovovalo nové struktuře.

Ale to je důvod, proč byste měli svá data procházet v shellu pomocí printjson() nejprve metodou.



  1. Existují nějaké nástroje pro odhad velikosti indexu v MongoDB?

  2. Jarní klíče řazení Redis

  3. Node.js a Mongodb - TypeError:undefined není funkce

  4. Jak agregovat vnořené vyhledávací pole v mongoose?