MongoDB
 sql >> Cơ Sở Dữ Liệu >  >> NoSQL >> MongoDB

Làm phẳng giản đồ mongoDB

Phản hồi mới

In dữ liệu

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

Cập nhật dữ liệu

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

Biểu mẫu đầu ra

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

Dữ liệu gốc

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

Câu trả lời ban đầu

Nếu bạn đang cố gắng "cập nhật" dữ liệu của mình, thì nó liên quan nhiều hơn những gì bạn đang cố gắng. Bạn có một số mảng và bạn cần thực sự "xem qua" các phần tử của mảng thay vì cố gắng truy cập trực tiếp vào chúng.

Đây chỉ là một mẫu để "in ra" dữ liệu "đã được làm phẳng":

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

Cái mà tôi tin là cung cấp cấu trúc mà bạn đang tìm kiếm:

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

}

Bây giờ tôi không tính đến bất kỳ khả năng nào bên trong "details" của bạn sắp xếp các tài liệu bằng các khóa như "a" vv có thể xuất hiện nhiều lần. Vì vậy, tôi chỉ đang xem xét rằng chỉ có 1 tài liệu bên trong đó có "a" hoặc "b" v.v. và giá trị tìm thấy cuối cùng khớp với khóa đó luôn được chỉ định khi thêm các khóa mới vào cấp cao nhất của "details" tài liệu.

Nếu trường hợp thực tế của bạn khác nhau, thì bạn sẽ cần sửa đổi các .forEach() khác nhau vòng lặp bên trong đó cũng sử dụng "chỉ mục" làm tham số và bao gồm giá trị chỉ mục đó như một phần của tên khóa. tức là:

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

Nhưng đó là chi tiết bạn sẽ phải tìm hiểu nếu cần vì điều này sẽ khác với cách dữ liệu được trình bày trong câu hỏi.

Tuy nhiên, nếu điều này hoàn toàn phù hợp với những gì bạn muốn cập nhật, thì chỉ cần chạy vòng lặp với .bulkWrite() các câu lệnh thực thi đều đặn:

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

Nó cũng xuất hiện từ _id các trường hiện diện trong mỗi tài liệu thành viên mảng mà bạn đang sử dụng mongoose. Vì vậy, bất cứ điều gì bạn làm, đừng thử và chạy mã bằng chính mongoose. Đây là bản cập nhật hàng loạt "một lần" cho dữ liệu của bạn và sẽ được chạy trực tiếp từ shell. Sau đó, tất nhiên bạn sẽ cần phải sửa đổi lược đồ của mình cho phù hợp với cấu trúc mới.

Nhưng đây là lý do tại sao bạn nên chạy qua dữ liệu của mình trong shell với printjson() phương pháp đầu tiên.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. cách gỡ lỗi từng bước trong bản đồ / giảm của mongodb

  2. Lấy một phần tử từ một mảng các đối tượng là một phần của một tài liệu (mongoose)

  3. Tôi có thể gọi rs.initiate () và rs.Add () từ node.js bằng trình điều khiển MongoDb không?

  4. Thiết kế MongoDB - thẻ

  5. Xác thực từ xa và cục bộ không thành công trên Mongo DB 3.0.7 (được cài đặt trên Amazon EC2)