0

您好,我在用户集合中有一个 MongoDB 文档:

{
   "_id": ObjectId("51d9534fc469880b338903eb"),
   "inbox": {
      "0": {},
      "1": {} ,
      "2": {} 
           ...
    },

}

根据要求,我需要每 5 分钟检查一次收件箱。所以我正在寻找:

  1. 查找收件箱的长度。
  2. 想象一下我的收件箱长度是 4,但是有 2 条新消息进来了,我怎么才能只收到那些新消息。

经过一番研究,我发现我可以使用 来检查我的收件箱中是否有任何新消息db.collection.find({ tags : { $size: 4 }});,但现在我的问题是如何找到这些新添加的消息。如果您能提出一个更好的方法来解决这种情况,那就太好了。

谢谢!

4

2 回答 2

0

您应该使用$slice运算符跳过数组中的一些项目:

db.collection.find({ tags : { $size : 4 } }, { inbox : { $slice : -4 } })

检查您的inbox字段是否真的是一个数组,因为在您的示例中它是一个文档。

也许您也应该修改查询,假设您有收件箱的长度,获取新消息将是:

var len = current_length; // comes from your app
var field = 'inbox.' + len;
// the query will check if the index "len" of inbox array exists
db.collection.find({ field : { $exists: true }, { inbox : { $slice : -len } }}

检查此问题以获取有关索引查询的更多信息:https ://stackoverflow.com/a/15224544/1877296

于 2013-07-08T16:37:21.793 回答
0

首先,设计模式的最佳方式是不使用对象inbox;你应该使用一个数组。

其次,但是,您知道什么是新消息(即 4 条消息中有 2 条是新消息)吗?我正在四处走动,说有一个read字段将是truefalse

所以你实际上最有可能问的是如何获取所有消息,按发送日期排序,在read哪里false; 或者,您也可以使用MongoDate( http://php.net/manual/en/class.mongodate.php )lastPullTime来跟踪它存储在$_SESSION.

在这个例子中,我们要去read现场。我还将假设您有一个ISODate()名为sent.

为此,我们可以像这样使用聚合框架:

db.collection.aggregate([
    // Let's get our user
    {$match:{_id:ObjectId()}},

    // Now we want to unwind the inbox so we can operate on it
    {$unwind:'$inbox'},

    // Now we want only messages that are not read
    {$match: {'inbox.read':false}},

    // Now lets do our sort by newest
    {$sort: {'inbox.sent':-1}},

    // Now lets group them back up
    {$group: {_id:'$_id', inbox: {$addToSet:'$inbox'}}}
])

或者你可以在 PHP 中使用asort on$doc['inbox']

于 2013-07-08T16:46:25.703 回答