[英]What is the best way to use collection as round robin in Mongodb
我有一個名為 items 的集合,其中包含三個文檔。
{
_id: 1,
item: "Pencil"
}
{
_id: 1,
item: "Pen"
}
{
_id: 1,
item: "Sharpner"
}
我如何查詢以循環方式獲取文檔? 考慮一下我同時收到多個用戶請求。
所以一個人應該得到Pencil其他人會得到Pen然后其他人會得到Sharpner 。
然后從第一個重新開始。
如果更改模式是一個選擇,我也准備好了。
我想我找到了一種無需更改架構即可執行此操作的方法。 它基於skip()
和limit()
。 此外,您可以指定保留返回文檔的內部排序順序,但是如指南所述,您不應依賴此順序,尤其是因為索引被覆蓋會導致性能下降:
$natural
參數根據項目在數據庫中的自然順序返回項目。 此排序是內部實現功能,您不應依賴其中的任何特定結構。
無論如何,這是查詢:
db.getCollection('YourCollection').find().skip(counter).limit(1)
counter
存儲文檔當前索引的位置。
幾件事開始..
話雖如此,假設您真的只想從數據庫中迭代,我會使用游標來完成此操作。 這將進行收集掃描,並且對於記錄來說效率非常低。
var myCursor = db.items.find().sort({_id:1});
while (myCursor.hasNext()) {
printjson(myCursor.next());
}
我的建議是您應該一次從數據庫中提取所有結果並在應用程序層中進行迭代。
var myCursor = db.inventory.find().sort({_id:1});
var documentArray = myCursor.toArray();
documentArray.foreach(doSomething)
如果這是關於分發的,您可以考慮通過aggregation/$sample獲取隨機文檔而不是循環法:
db.collection.aggregate([
{
"$sample": {
"size": 1
}
}
])
或者有通過$rand隨機化的選項...
重組數據對象后使用文本 findOneAndUpdate
db.counter.findOneAndUpdate( {}, pipeline)
{
"_id" : ObjectId("624317a681e72a1cfd7f2b7e"),
"values" : [
"Pencil",
"Pen",
"Sharpener"
],
"selected" : "Pencil",
"counter" : 1
}
db.counter.findOneAndUpdate( {}, pipeline)
{
"_id" : ObjectId("624317a681e72a1cfd7f2b7e"),
"values" : [
"Pencil",
"Pen",
"Sharpener"
],
"selected" : "Pen",
"counter" : 2
}
數據 object 現在在哪里:
{
"_id" : ObjectId("6242fe3bc1551d0f3562bcb2"),
"values" : [
"Pencil",
"Pen",
"Sharpener"
],
"selected" : "Pencil",
"counter" : 1
}
管道是:
[{$project: {
values: 1,
selected: {
$arrayElemAt: [
'$values',
'$counter'
]
},
counter: {
$mod: [
{
$add: [
'$counter',
1
]
},
{
$size: '$values'
}
]
}
}}]
這有一些優點:
問題:對於超過 10 個條目,此方法會很笨拙
很難證明此方法是否像宣傳的那樣有效,因此有一個附帶的 Kotlin 項目。 該項目使用協程,因此它異步調用查找/更新。
備選方案(假設 50K 個項目而不是 3 個):設置一個簡單的計數器 {counter: 0} 並更新如下:
db.counter.findOneAndUpdate({},
[{$project: {
counter: {
$mod: [
{
$add: [
'$counter',
1
]
},
50000
]
}
}}])
然后使用簡單的 select 查詢來查找正確的文檔。
我已經更新了 github 以包含此示例。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.