Javascript 是否更正Mongoose语法以查询user1存档的邮件?

Javascript 是否更正Mongoose语法以查询user1存档的邮件?,javascript,node.js,mongodb,mongoose,Javascript,Node.js,Mongodb,Mongoose,这是查找user1收到的所有文档的正确查询吗?其中,对于user1,archive=true var query = { "to.username": user1, "to.section.archive": true }; Models.Message.find( query ).sort([['to.updated','descending']]).exec(function (err, messages) { 消息架构的示例嵌入“To”数组如下所示: "

这是查找user1收到的所有文档的正确查询吗?其中,对于user1,archive=true

var query = {
        "to.username": user1,
        "to.section.archive": true
};

Models.Message.find( query ).sort([['to.updated','descending']]).exec(function (err, messages) {
消息架构的示例嵌入“To”数组如下所示:

"to" : [ 
    {
        "user" : ObjectId("53b96c735f4a3902008aa019"),
        "username" : "user1",
        "updated" : ISODate("2014-07-08T06:23:43.000Z"),
        "_id" : ObjectId("53bb8e6f1e2e72fd04009dad"),
        "section" : {
            "in" : true,
            "out" : false,
            "archive" : true
        }
    }
]
查询应该只返回上面的文档(user1和archive为true)…而不是下一个文档(archive为true,但不是user1):

您希望操作符选择同时具有条件和投影操作符的元素:

Models.Message.find(
   { 
       "to": { 
           "$elemMatch": {
              "username": "user2",
              "section.archive": true
           }
       }
   },
   { "created": 1, "message": 1, "to.$": 1 }
).sort([['to.updated','descending']]).exec(function (err, messages) {

});
请注意,此仅在匹配投影的“第一”元素时起作用。此外,您还希望对匹配数组元素的值进行“排序”,而使用
.find()
.sort()
修饰符无法进行排序

如果希望数组中有多个匹配项,则需要使用聚合方法。这样做比其他方式更复杂的“过滤”和“投影”:

Models.Message.aggregate([

   // Match documents
   { "$match": {
        "to": { 
            "$elemMatch": {
               "username": "user2",
               "section.archive": true
            }
        }
   }},

   // Unwind to de-normalize
   { "$unwind": "$to" },

   // Match the array elements      
   { "$match": {
       "to.username": "user2",
       "to.section.archive": true
   }},

   // Group back to the original document
   { "$group": {
       "_id": "$_id",
       "created": { "$first": "$created" },
       "message": { "$first": "$message" },
       "to": { "$push": "$to" }
   }}

   // Sort the results "correctly"
   { "$sort": { "to.updated": -1 } }

],function(err,messages) {

});
或者,您可以通过在MongoDB 2.6或更高版本中对运算符应用一些逻辑来避免使用and。只需观察数组内容是否“真正”唯一,就像应用于生成的“过滤”数组一样:

甚至使用:

但在文档的所有级别上操作时要小心,这样您的结果可能会出乎意料


很可能您的“to”数组实际上只有一个匹配的条目,所以一般来说,标准投影应该可以。但以下是如何使用MongoDB在数组元素中进行“多次”匹配。

您建议使用什么方法返回每个匹配文档的全部内容?在测试之后,我使用$unwind+$group AGGRAGRATION,所有其他字段都使用$first累计。在最佳实践中,这一排名如何?@StackThis刚刚注意到,您当然希望对匹配元素的“更新”日期进行“排序”。因此,您当然需要一个聚合方法来实现这一点。你正在做的很好,其他方法是新的介绍。如果要查找多个数组匹配项,您可能还需要在分组中投影一个
$min
$max
日期值以进行排序。甚至可能在分组之前对这些匹配项进行排序。感谢您的更新。。当你的更新出现时,我正在研究聚合的$sort语法!很高兴看到所有的方法,非常感谢您的体贴和支持insight@StackThis最近还发布了一篇文章,其中显示了从数组中提取某些内容以进行排序。更复杂一点,但涵盖了一般原则,如果您有多个数组匹配,您需要决定排序的值。Thaks for the head up。。作品中有一个可以直接从中受益的特点。。仔细考虑一下,然后再仔细看看这篇文章。。最好的,
Models.Message.aggregate([

   // Match documents
   { "$match": {
        "to": { 
            "$elemMatch": {
               "username": "user2",
               "section.archive": true
            }
        }
   }},

   // Unwind to de-normalize
   { "$unwind": "$to" },

   // Match the array elements      
   { "$match": {
       "to.username": "user2",
       "to.section.archive": true
   }},

   // Group back to the original document
   { "$group": {
       "_id": "$_id",
       "created": { "$first": "$created" },
       "message": { "$first": "$message" },
       "to": { "$push": "$to" }
   }}

   // Sort the results "correctly"
   { "$sort": { "to.updated": -1 } }

],function(err,messages) {

});
Models.Message.aggregate([
   { "$match": {
        "to": { 
            "$elemMatch": {
               "username": "user2",
               "section.archive": true
            }
        }
   }},
   { "$project": {
       "created": 1,
       "message": 1,
       "_id": 1,
       "to": {
           "$setDifference": [
               {
                   "$map": {
                       "input": "$to",
                       "as": "el",
                       "in": {
                           "$cond": [
                                {
                                    "$and": [
                                        { "$eq": [ "$$el.username", "user2" ] },
                                        "$$el.section.archive"
                                    ]
                                },
                                "$$el",
                                false
                            ]
                       }
                   }
               },
               [false]
           ]
       }
   }},
   { "$sort": { "to.updated": -1 } }

],function(err,messages) {

});
Models.Messages.aggregate([
   { "$match": {
        "to": { 
            "$elemMatch": {
               "username": "user2",
               "section.archive": true
            }
        }
   }},
   { "$redact": {
       "$cond": {
           "if": {
               "$and": [
                   { "$eq": [ 
                       { "$ifNull": [ "$username", "user2" ] },
                       "user2"
                   ] },
                   { "$ifNull": [ "$section.archive", true ] }
               ]
           },
           "then": "$$DESCEND",
           "else": "$$PRUNE"
       }
   }},
   { "$sort": { "to.updated": -1 } }
],function(err,messages) {

});