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

Udfladning af mongoDB-skema

Nyt svar

Udskriv dataene

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);
});

Opdater dataene

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 = [];
}

Outputformular

{
    "_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"
        }
    ]
}

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

Originalt svar

Hvis du forsøger at "opdatere" dine data, så er det meget mere involveret, end det du prøver. Du har flere arrays, og du skal faktisk "gennemløbe" array-elementerne i stedet for at forsøge at få direkte adgang til dem.

Her er blot et eksempel til at "udskrive" de "fladede" 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);
})

Hvilket jeg tror giver den struktur, du leder efter:

{
    "_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"
        }
    ]

}

Nu tager jeg ikke højde for nogen mulighed i dine "details" array dokumenterne med nøgler som "a" osv kunne måske dukke op flere gange. Så jeg overvejer bare, at der kun er 1 dokument derinde, som har et "a" eller en "b" osv., og den sidst fundne værdi, der matcher denne nøgle, tildeles altid, når de nye nøgler tilføjes til det øverste niveau af "details" dokumenter.

Hvis din faktiske sag varierer, så skal du ændre forskellige .forEach() sløjfer inde der for også at bruge "indekset" som en parameter og inkludere den indeksværdi som en del af nøglenavnet. dvs.:

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

Men det er en detalje, du bliver nødt til at finde ud af, hvis det er nødvendigt, da dette ville afvige fra, hvordan dataene præsenteres i spørgsmålet.

Hvis dette imidlertid passer perfekt til det, du vil opdatere til, så kør blot løkken med .bulkWrite() sætninger, der udføres med regelmæssige intervaller:

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 = [];
}

Det fremgår også af _id felter til stede i hvert array-medlemsdokument, som du bruger mongoose. Så uanset hvad du gør, så prøv ikke at køre koden ved at bruge mongoose selv. Det er en "engangs" masseopdatering af dine data og bør køres direkte fra skallen. Så skal du selvfølgelig ændre dit skema, så det passer til den nye struktur.

Men dette er grunden til, at du skal køre dine data igennem i skallen med printjson() metode først.



  1. Mongoose sub document pre remove middleware ikke kaldt

  2. E-Commerce API lavet med Node-Js, Typescript, PostgreSQL, Redis og Kafka

  3. kører flere forekomster af mongod as service

  4. Python og MongoDB databaseudvikling