我正在努力撰寫一個可以參考和更新陣列中物件的 Mongo UpdateMany陳述句。
在這里,我創建了 3 個檔案。每個檔案都有一個名為 always 的陣列innerArray,其中包含一個物件和一個日期欄位。
use test;
db.innerArrayExample.insertOne({ _id: 1, "innerArray": [ { "originalDateTime" : ISODate("2022-01-01T01:01:01Z") } ]});
db.innerArrayExample.insertOne({ _id: 2, "innerArray": [ { "originalDateTime" : ISODate("2022-01-02T01:01:01Z") } ]});
db.innerArrayExample.insertOne({ _id: 3, "innerArray": [ { "originalDateTime" : ISODate("2022-01-03T01:01:01Z") } ]});
我想添加一個基于原始日期欄位的新日期欄位,以結束:
{ _id: 1, "innerArray": [ { "originalDateTime" : ISODate("2022-01-01T01:01:01Z"), "copiedDateTime" : ISODate("2022-01-01T12:01:01Z") } ]}
{ _id: 2, "innerArray": [ { "originalDateTime" : ISODate("2022-01-02T01:01:01Z"), "copiedDateTime" : ISODate("2022-01-02T12:01:01Z") } ]}
{ _id: 3, "innerArray": [ { "originalDateTime" : ISODate("2022-01-03T01:01:01Z"), "copiedDateTime" : ISODate("2022-01-03T12:01:01Z") } ]}
在偽代碼中,我說的是originalDateTime,通過一個函式運行它并添加一個相關的copiedDateTime值。
對于我的特定用例,我要運行的函式從 剝離時區originalDateTime,然后用新的時區覆寫它,相當于 JavaZonedDateTime函式withZoneSameLocal。也就是 UTC 晚上 9 點變成布魯塞爾晚上 9 點(因此實際上是 UTC 晚上 7 點)。技術理由和方法論已在此處的另一個 Stack Overflow 問題中得到解答。
我正在努力處理的查詢部分是從陣列中的元素更新/選擇資料的部分。在我的簡單示例中,例如我制作了這個查詢,但不幸的是它不起作用:
此函式放置copiedDateTime在正確的位置......但不評估操作日期的命令:
db.innerArrayExample.updateMany({ "innerArray.0.originalDateTime" : { $exists : true }}, { $set: { "innerArray.0.copiedDateTime" : { $dateFromString: { dateString: { $dateToString: { "date" : "$innerArray.0.originalDateTime", format: "%Y-%m-%dT%H:%M:%S.%L" }}, format: "%Y-%m-%dT%H:%M:%S.%L", timezone: "Europe/Paris" }}});
// output
{
_id: 1,
innerArray: [
{
originalDateTime: ISODate("2022-01-01T01:01:01.000Z"),
copiedDateTime: {
'$dateFromString': {
dateString: { '$dateToString': [Object] },
format: '%Y-%m-%dT%H:%M:%S.%L',
timezone: 'Europe/Paris'
}
}
}
]
}
這個簡化的查詢,也有同樣的問題:
b.innerArrayExample.updateMany({ "innerArray.0.originalDateTime" : { $exists : true }}, { $set: { "innerArray.0.copiedDateTime" : "$innerArray.0.originalDateTime" }});
//output
{
_id: 1,
innerArray: [
{
originalDateTime: ISODate("2022-01-01T01:01:01.000Z"),
copiedDateTime: '$innerArray.0.originalDateTime'
}
]
}
如您所見,這個問題看起來與其他堆疊溢位問題是分開的。它不是能夠改變時區,而是讓陣列內部的東西更新。
我計劃使用這個查詢,使用不同的位置/時區組合創建它的 70,000 個變體,并針對具有數百萬條記錄的資料庫運行它,所以我更喜歡使用updateMany而不是使用 Javascript 來迭代資料庫中的每一行的東西。 . 除非這是唯一可行的解??決方案。
我試過放在$set方括號里。這改變了它解釋一切的方式,評估右側,但會導致其他問題:
test> db.innerArrayExample.updateMany({ "_id" : 1 }, [{ $set: { "innerArray.0.copiedDateTime" : "$innerArray.0.originalDateTime" }}]);
//output
{
_id: 1,
innerArray: [
{
'0': { copiedDateTime: [] },
originalDateTime: ISODate("2022-01-01T01:01:01.000Z")
}
]
}
上面它似乎解釋了.0。作為文字而不是陣列元素。(出于我的需要,我知道該陣列始終只有一項)。我不知所措地找到了一個滿足我需要的例子。
我也嘗試過使用arrayFilters, 記錄在我的 mongo updateMany 檔案中,但我無法理解它是如何與物件一起作業的:
test> db.innerArrayExample.updateMany(
... { },
... { $set: { "innerArray.$[element].copiedDateTime" : "$innerArray.$[element].originalDateTime" } },
... { arrayFilters: [ { "originalDateTime": { $exists: true } } ] }
... );
MongoServerError: No array filter found for identifier 'element' in path 'innerArray.$[element].copiedDateTime'
test> db.innerArrayExample.updateMany(
... { },
... { $set: { "innerArray.$[0].copiedDateTime" : "$innerArray.$[element].originalDateTime" } },
... { arrayFilters: [ { "0.originalDateTime": { $exists: true } } ] }
... );
MongoServerError: Error parsing array filter :: caused by :: The top-level field name must be an alphanumeric string beginning with a lowercase letter, found '0'
如果有人可以幫助我理解 Mongo 語法的微妙之處并幫助我回到正確的道路上,我將不勝感激。
uj5u.com熱心網友回復:
您想使用流水線更新,您使用的語法遇到的問題是它不允許使用聚合運算子和檔案欄位值。
這是一個有關如何執行此操作的快速示例:
db.collection.updateMany({},
[
{
"$set": {
"innerArray": {
$map: {
input: "$innerArray",
in: {
$mergeObjects: [
"$$this",
{
copiedDateTime: "$$this.originalDateTime"
}
]
}
}
}
}
}
])
蒙戈游樂場
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/465217.html
