在mongodb中如何给列表按时间排序
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在mongodb中如何给列表按时间排序相关的知识,希望对你有一定的参考价值。
参考技术A 时间降序:db.somecollection.find().sort( time : -1 );
如何将项目存储在 MongoDb 的排序列表中?
【中文标题】如何将项目存储在 MongoDb 的排序列表中?【英文标题】:How to store items in a sorted list in MongoDb? 【发布时间】:2018-08-07 08:58:19 【问题描述】:我正在使用 MongoDb 构建出版物轮换解决方案。
例如,客户有 1000 种产品,并且在任何时候,订阅者都应该可以使用其中的 200 种产品。其余的 (800) 应该采用轮换模式,每天发布一个产品而另一个未发布,这样 800 天后就会发生完整的轮换。
我最初的想法是简单地将 ID 引用存储在两个新集合中:
products_published
products_unpublished
然后,每天,shift()
将来自 products_published
和 unshift()
的项目放入 products_unpublished
,同时将 pop()
来自 products_unpublished
和 push()
的项目放入 @987654331 @:
也许是一个非常幼稚的轮换尝试。但这似乎很简单。
最后的要求是这个旋转顺序必须可以通过一些 UI 进行编辑。
问题在于 MongoDb 似乎不能保证自然顺序,也不容易在集合中的确切位置插入文档、移动它们等。
我真的不想在我的文档上维护我自己的order
属性,因为每次轮换我都必须增加每个文档的order
。
我还考虑将所有这些数据保存在包含两个数组的单个文档中,因为文档中的数组本身确实以安全的方式保持顺序。然而,这让人感觉很脏,而且很容易在未来出现问题。
经过大量谷歌搜索,我没有找到关于如何使用 MongoDb 维护有序集合的好答案。
我不想使用硬编码的日期,因为将来轮换频率可能会变为一天两次、一天三次等。
有什么建议吗?
【问题讨论】:
【参考方案1】:添加 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_date
s 以使新订单生效。
例子:
// 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更新
【讨论】:
我不想使用硬编码的日期,因为未来的轮换频率可能会变为一天两次、一天三次等。 另外,我认为您的解决方案甚至都行不通。用户需要能够修改轮换顺序...不仅仅是“初始”顺序。 ISODate 具有毫秒精度。对不起,如果名称有误导性。 在轮换期间在轮换期间弄乱轮换顺序是一个值得商榷的功能,但我将其留给企业来处理后果。您如何在轮换期间重新定义顺序?移动列表中的一项?更新整个粉色堆栈的顺序? 我知道它具有毫秒精度。我宁愿将轮换间隔逻辑保留在单独的 rotator-microservice 中,并且只在数据库级别保留轮换 order 。旋转是恒定的,因此当然任何重新排序都会在旋转期间发生。最简单的方法是简单地交换任意两个产品的位置。以上是关于在mongodb中如何给列表按时间排序的主要内容,如果未能解决你的问题,请参考以下文章