MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Spłaszczanie schematu mongoDB

Nowa odpowiedź

Drukuj dane

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

Zaktualizuj dane

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

Formularz wyjściowy

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

Oryginalne dane

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

Oryginalna odpowiedź

Jeśli próbujesz „zaktualizować” swoje dane, jest to o wiele bardziej skomplikowane niż to, czego próbujesz. Masz kilka tablic i musisz faktycznie „przechodzić” przez elementy tablicy, zamiast próbować uzyskać do nich bezpośredni dostęp.

Oto tylko próbka „wydrukowania” „spłaszczonych” danych:

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 moim zdaniem daje strukturę, której szukasz:

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

}

Teraz nie biorę pod uwagę żadnej możliwości, że wewnątrz twoich "details" ułóż dokumenty w tablicy z kluczami takimi jak "a" itp. może pojawić się wiele razy. Rozważam więc, że w środku znajduje się tylko 1 dokument, który ma "a" lub "b" itd., a ostatnia znaleziona wartość pasująca do tego klucza jest zawsze przypisywana podczas dodawania nowych kluczy do najwyższego poziomu "details" dokumenty.

Jeśli rzeczywisty przypadek jest różny, musisz zmodyfikować różne .forEach() pętle wewnątrz, aby również użyć "indeksu" jako parametru i uwzględnić tę wartość indeksu jako część nazwy klucza. czyli:

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

Ale jest to szczegół, który będziesz musiał opracować w razie potrzeby, ponieważ różniłoby się to od sposobu przedstawienia danych w pytaniu.

Jeśli jednak jest to idealne dopasowanie do tego, do czego chcesz zaktualizować, po prostu uruchom pętlę za pomocą .bulkWrite() oświadczenia wykonywane w regularnych odstępach czasu:

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

Pojawia się również z _id pola obecne w każdym dokumencie składowym tablicy, którego używasz mangusty. Więc cokolwiek robisz, nie próbuj uruchamiać kodu za pomocą samej mangusty. Jest to „jednorazowa” zbiorcza aktualizacja danych i powinna być uruchamiana bezpośrednio z powłoki. Wtedy oczywiście będziesz musiał zmodyfikować swój schemat, aby pasował do nowej struktury.

Ale właśnie dlatego powinieneś przeglądać swoje dane w powłoce za pomocą printjson() najpierw metoda.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Agregacja Mongodb $grupa, ogranicz długość tablicy

  2. Połączenie z mangustą

  3. Uruchom migrację bazy danych (mongodb) za pomocą node.js

  4. Nie można zaimportować pliku json w MongoDB

  5. Jak określić kolejność lub sortowanie przy użyciu sterownika C# dla MongoDB?