新しい応答
データを印刷する
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);
});
データを更新する
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 = [];
}
出力フォーム
{
"_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"
}
]
}
元のデータ
{
"_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")
}
]
}
]
}
]
}
元の回答
データを「更新」しようとしている場合、それはあなたが試みているものよりもはるかに複雑です。いくつかの配列があり、それらに直接アクセスしようとするのではなく、実際に配列要素を「トラバース」する必要があります。
これは、「フラット化された」データを「印刷」するためのサンプルです。
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);
})
これはあなたが探している構造を与えると私は信じています:
{
"_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"
}
]
}
今、私はあなたの"details"
の中にある可能性を考慮していません "a"
のようなキーでドキュメントを配列します などが複数回表示される可能性があります。したがって、"a"
を持つドキュメントは1つしかないと考えています。 または"b"
など、およびそのキーに一致する最後に見つかった値は、"details"
のトップレベルに新しいキーを追加するときに常に割り当てられます ドキュメント。
実際のケースが異なる場合は、さまざまな.forEach()
を変更する必要があります。 その中でループして、「インデックス」をパラメータとして使用し、そのインデックス値をキー名の一部として含めます。つまり:
"a0Unit": "08",
"a0Size": "05",
"a1Unit": "09",
"a1Size": "06"
ただし、これは質問でのデータの表示方法とは異なるため、必要に応じて解決する必要がある詳細です。
ただし、これが更新したいものに完全に適合する場合は、 .bulkWrite()
定期的に実行されるステートメント:
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 = [];
}
_id
からも表示されます マングースを使用している各配列メンバードキュメントに存在するフィールド。したがって、何をするにしても、マングース自体を使用してコードを実行しようとしないでください。これはデータの「1回限りの」一括更新であり、シェルから直接実行する必要があります。その後、もちろん、新しい構造に合わせてスキーマを変更する必要があります。
ただし、これが、printjson()
を使用してシェル内のデータを実行する必要がある理由です。 最初の方法。