添加 2 个属性:order 和 published_date。
前者为用户定义初始顺序。后者供您旋转。
获取下一个的查询:
db.collection.find({}).sort({published_date: 1, order: 1}).limit(1)
推送/弹出更新:
db.collection.update({_id}, {$set:{published_date: new ISODate()}})
在order 更改时,删除所有published_dates 以使新订单生效。
例子:
// initial data
db.collection.insert([
{_id:1, order:2},
{_id:2, order:1},
{_id:3, order:3}
])
// pick the first document
db.collection.find({}).sort({published_date: 1, order: 1}).limit(1)
// returns you {_id:2, order:1}
// rotating it:
db.collection.update({_id:2}, {$set:{published_date: new ISODate()}})
// pick the first document
db.collection.find({}).sort({published_date: 1, order: 1}).limit(1)
// returns you {_id:1, order:2}
// rotating it:
db.collection.update({_id:1}, {$set:{published_date: new ISODate()}})
// pick the first document
db.collection.find({}).sort({published_date: 1, order: 1}).limit(1)
// returns you {_id:3, order:3}
// rotating it:
db.collection.update({_id:1}, {$set:{published_date: new ISODate()}})
// pick the first document
db.collection.find({}).sort({published_date: 1, order: 1}).limit(1)
// returns you {_id:2, order:1, published_date: 2018-02-27T18:28:20.330Z}
etc, etc, etc until end of days at 15:30:08 on Sunday, December 4th in the year 292,277,026,596 AC
如果您不喜欢将日期作为自然的自动递增值,则可以单独使用订单字段。
推送/弹出更新将是:
db.collection.update({_id}, {$inc:{order: <number of documents in rotation>}})
但它需要不时对$dec 柜台进行一些内务处理,并且单个文档的转移变得复杂。
或者,您可以考虑将 ID 保存在单个文档中,而不是集合中:
{
refs: [
product_id,
product_id,
product_id,
]
}
如果它适合单个文档的 16MB 限制。
数组中元素的顺序被保留:http://www.rfc-editor.org/rfc/rfc7159.txt,你可以使用常规的$push/$pop更新