返回在mongoDB中具有数组的字段,并返回该数组中的第一个和最后一个值

时间:2014-07-24 17:20:09

标签: json node.js mongodb mongoose aggregation-framework

场景:在名为twitCount的集合中考虑MongoDB中存在的文档。

{
"_id" : ObjectId("53d1340478441a1c0d25c40c"),
"items" : [ 
    {
        "date" : ISODate("2014-07-22T22:18:05.000Z"),
        "value" : 4,
        "_id" : ObjectId("53d134048b3956000063aa72")
    }, 
    {
        "date" : ISODate("2014-07-21T22:09:20.000Z"),
        "value" : 10,
        "_id" : ObjectId("53d134048b3956000063aa71")
    }
   ...
],
"ticker" : "OM:A1M"

}

我只想获取" items" 中的第一个和最后一个日期。我已经尝试过很多不同的"查询"。但我无法做到对。 "自动收报机"是独一无二的

以下查询是唯一返回内容的查询,但它返回所有内容(预期)。

    twitCount.aggregate([{ $match : { ticker: theTicker}} ], function(err, result){
                if (err) {
                  console.log(err);
                    return;
                }
             console.log(result)


            })

所以,最后我希望查询返回类似这样的内容[2013-02-01,2014-07-24]; 我真的需要帮助,手册/核心/聚合上的所有链接都是紫色的,我不知道从哪里获取更多信息。

1 个答案:

答案 0 :(得分:0)

很难判断您的意图是使用单个文档还是符合您条件的多个文档。正如所建议的那样,单个文档实际上只涉及使用JavaScript本机的shiftpop方法来获取单数结果以获取数组的第一个和最后一个元素。您可能还需要在此处使用数组排序

 twitCount.findOne({ "ticker": "OM:A1M" },function(err,doc) {

     doc.items = doc.items.sort(function(a,b) {
         return ( a.date.valueOf() > b.date.valueOf() ) ? 1
            : ( a.date.valueOf() < b.date.valueOf() ) ? -1 : 0;
     });
     doc.items =  [doc.items.shift(),doc.items.pop()];

     console.log( doc );
 })

其他建议并不适用,因为像$pop之类的运算符会在更新中永久地对数组进行mondized。如果数组内容已经排序,那么可以在查询中使用的$slice运算符实际上只对你有用,另外你会先做两个查询来返回第一个和最后一个,这不是你的想。

但是,如果您真的希望在多个文档上执行此操作,那么聚合框架就是答案。使用数组时要理解的关键区域是必须首先在阵列上使用$unwind管道阶段。这将“去规范化”为一种形式,其中为每个数组元素有效地生成文档的副本:

twitCount.aggregate([
    // Match your "documents" first
    { "$match": { "ticker": "OM:A1M" } },

    // Unwind the array
    { "$unwind": "$items" },

    // Sort the values
    { "$sort": { "items.date": 1 } },

    // Group with $first and $last items
    { "$group": {
       "_id": "$ticker",
       "first": { "$first": "$items" },
       "last": { "$last": "$items" }
    }}
],function(err,result) {

如果你真的希望“项目”作为一个数组返回,那么你可以做一些不同的事情:

twitCount.aggregate([
    // Match your "documents" first
    { "$match": { "ticker": "OM:A1M" } },

    // Unwind the array
    { "$unwind": "$items" },

    // Sort the values
    { "$sort": { "items.date": 1 } },

    // Group with $first and $last items
    { "$group": {
       "_id": "$ticker",
       "first": { "$first": "$items" },
       "last": { "$last": "$items" },
       "type": { "$first": { "$const": [true,false] } }
    }},

    // Unwind the "type"
    { "$unwind": "$type" },

    // Conditionally push to the array
    { "$group": {
        "_id": "$_id",
        "items": {
           "$push": {
               "$cond": [
                   "$type",
                   "$first",
                   "$last"
               ]
           }
        }
    }}
],function(err,result) {

或者,如果您的$match语句只是想要选择,并且您希望每个文档中的“第一个”和“最后一个”“_id”,那么您只需将初始$group中的密钥更改为“ $ _id“而不是”$ ticker“字段值:

twitCount.aggregate([
    // Match your "documents" first
    { "$match": { "ticker": "OM:A1M" } },

    // Unwind the array
    { "$unwind": "$items" },

    // Sort the values
    { "$sort": { "items.date": 1 } },

    // Group with $first and $last items
    { "$group": {
       "_id": "$_id",
       "ticker": { "$first": "$ticker" },
       "first": { "$first": "$items" },
       "last": { "$last": "$items" },
       "type": { "$first": { "$const": [true,false] } }
    }},

    // Unwind the "type"
    { "$unwind": "$type" },

    // Conditionally push to the array
    { "$group": {
        "_id": "$_id",
        "ticker": { "$first": "$ticker" },
        "items": {
           "$push": {
               "$cond": [
                   "$type",
                   "$first",
                   "$last"
               ]
           }
        }
    }}
],function(err,result) {

在最后一种情况下,根据您提供的数据,您会得到类似的结果:

{
    "_id" : ObjectId("53d1340478441a1c0d25c40c"),
    "ticker" : "OM:A1M",
    "items" : [
            {
                    "date" : ISODate("2014-07-21T22:09:20Z"),
                    "value" : 10,
                    "_id" : ObjectId("53d134048b3956000063aa71")
            },
            {
                    "date" : ISODate("2014-07-22T22:18:05Z"),
                    "value" : 4,
                    "_id" : ObjectId("53d134048b3956000063aa72")
            }
    ]
}

您可以在文档中找到Full List of Aggregation Operators。值得了解这些功能如何取决于您正在做什么聚合框架可以是一个非常有用的工具。