MongoDB 一组具有限制大小的值
MongoDB set of values with a limit size
我正在通过将交易保存到数据库列表来更新交易列表,我不想在列表中有重复的条目所以我使用 $addtoset
这是因为可以多次触发请求,我们希望确保任何更改对数据库都是幂等的。现在唯一的问题是我们只想存储 最新的 20 笔交易
这可以通过 $push
$sort
$slice
来完成,但我需要确保没有重复的条目。早在 2015 年就曾向 mongo 提出过将此功能添加到 $addtoset
功能的功能请求,但由于 'sets' 未在订单中,他们拒绝了此功能...
$sort 函数应该是什么
我想我可以简单地将一个空的推送更新附加到更新对象,但据我了解,每个更新都可能是线程化的,如果 push/slice 在 [=12] 之前触发,则可能导致不希望的编辑=]
现在,这些值是具有以下公式的聚合字符串
timestamp:value
但我可以轻松地将结构更改为对象
{ts:timestamp, value:value}
更新:
当前代码,不确定它是否会按预期工作,因为每个操作可能是独立的
await historyDB
.updateOne(
{ trxnId: txid },
{
$addToSet: {
history: {
ts: time,
bid: bid.value,
txid: trxn.txid,
}
},
$push: {
history: {
$each: [{ts:-1}],
$sort: { ts: 1 },
$slice: -10,
},
},
},
{ upsert: true },
).exec();
您的查询无效,因为您正尝试更新 history
多次,这在简单 更新文档 中是不允许的,并引发错误 Updating the path 'history' would create a conflict at 'history'
.
您随后可以使用 聚合管道 .
多次更新 history
字段
await historyDB.updateOne(
{ trxnId: txid},
[{
$set: {
history: {
$let: {
vars: {
historyObj: {
ts: time,
bid: bid.value,
txid: trxn.txid,
},
historySafe: { $ifNull: ["$history", []] }
},
in: {
$cond: {
if: { $in: ["$$historyObj", "$$historySafe"] },
then: "$history",
else: { $concatArrays: [ "$$historySafe", ["$$historyObj"] ] }
}
}
}
}
},
},
{
$set: {
history: {
$function: {
body: function(entries) {
entries.sort((a, b) => a.ts - b.ts);
return entries;
},
args: [{ $ifNull: ["$history", []] }],
lang: "js"
}
}
},
},
{
$set: {
history: {
$slice: [ "$history", -10 ]
}
}
}],
{ upsert: true },
).exec()
从 MongoDB 6.0 开始,提供排序的第二个 $set
阶段可以替换为 $sortArray
运算符(参见 here)。
我正在通过将交易保存到数据库列表来更新交易列表,我不想在列表中有重复的条目所以我使用 $addtoset
这是因为可以多次触发请求,我们希望确保任何更改对数据库都是幂等的。现在唯一的问题是我们只想存储 最新的 20 笔交易
这可以通过 $push
$sort
$slice
来完成,但我需要确保没有重复的条目。早在 2015 年就曾向 mongo 提出过将此功能添加到 $addtoset
功能的功能请求,但由于 'sets' 未在订单中,他们拒绝了此功能...
$sort 函数应该是什么
我想我可以简单地将一个空的推送更新附加到更新对象,但据我了解,每个更新都可能是线程化的,如果 push/slice 在 [=12] 之前触发,则可能导致不希望的编辑=]
现在,这些值是具有以下公式的聚合字符串
timestamp:value
但我可以轻松地将结构更改为对象
{ts:timestamp, value:value}
更新: 当前代码,不确定它是否会按预期工作,因为每个操作可能是独立的
await historyDB
.updateOne(
{ trxnId: txid },
{
$addToSet: {
history: {
ts: time,
bid: bid.value,
txid: trxn.txid,
}
},
$push: {
history: {
$each: [{ts:-1}],
$sort: { ts: 1 },
$slice: -10,
},
},
},
{ upsert: true },
).exec();
您的查询无效,因为您正尝试更新 history
多次,这在简单 更新文档 中是不允许的,并引发错误 Updating the path 'history' would create a conflict at 'history'
.
您随后可以使用 聚合管道 .
多次更新history
字段
await historyDB.updateOne(
{ trxnId: txid},
[{
$set: {
history: {
$let: {
vars: {
historyObj: {
ts: time,
bid: bid.value,
txid: trxn.txid,
},
historySafe: { $ifNull: ["$history", []] }
},
in: {
$cond: {
if: { $in: ["$$historyObj", "$$historySafe"] },
then: "$history",
else: { $concatArrays: [ "$$historySafe", ["$$historyObj"] ] }
}
}
}
}
},
},
{
$set: {
history: {
$function: {
body: function(entries) {
entries.sort((a, b) => a.ts - b.ts);
return entries;
},
args: [{ $ifNull: ["$history", []] }],
lang: "js"
}
}
},
},
{
$set: {
history: {
$slice: [ "$history", -10 ]
}
}
}],
{ upsert: true },
).exec()
从 MongoDB 6.0 开始,提供排序的第二个 $set
阶段可以替换为 $sortArray
运算符(参见 here)。