【问题标题】:MongoDB Facet results formattingMongoDB Facet 结果格式
【发布时间】:2018-01-10 01:58:56
【问题描述】:

我有一个带有 $facet 的查询构造,它以这种格式返回结果:

{price_now: [
   { _id: 'apple', price_now: 1.02 },
   { _id: 'melon', price_now: 3.18 },
   { _id: 'cherry', price_now: 2.57 }],
price_15m: [
   { _id: 'apple', price_15m: 1.08 },
   { _id: 'melon', price_15m: 3.12 },
   { _id: 'cherry', price_15m: 2.82 }],
price_30m: [
   { _id: 'apple', price_30m: 1.05 },
   { _id: 'melon', price_30m: 3.04 },
   { _id: 'cherry', price_30m: 2.94 }]

我怎样才能得到这种格式的结果?:

{ _id: 'apple', price_now: 1.02, price_15m: 1.08, price_30m: 1.05 },
{ _id: 'melon', price_now: 3.18, price_15m: 3.12, price_30m: 3.04 },
{ _id: 'cherry', price_now: 2.57, price_15m: 2.82, price_30m: 2.94 }

完整的查询如下所示:

var today = new Date();
var shift_15m = new Date(today.getTime()-15*60*1000);
var shift_30m = new Date(today.getTime()-30*60*1000);

food.aggregate( [
    {
        $facet: {
            price_now: [
                {
                    $group: {
                        _id: "$name",
                        price_now: {$last: "$price"}
                    }
                }
            ],
            price_15m: [
                {
                    $match: {
                        date: { "$lte": shift_15m }
                    }
                }, {
                    $group: {
                        _id: "$name",
                        price_5m: {$last: "$price"}
                    }
                }
            ],
            price_30m: [
                {
                    $match: {
                        date: { "$lte": shift_30m }
                    }
                }, {
                    $group: {
                        _id: "$name",
                        price_30m: {$last: "$price"}
                    }
                }
            ]
        }
    }
])

我需要在一个查询中获取不同时间间隔的每种产品的价格。也许您知道一种更好更快的方法来获取不同时间的价格。 我的 MongoDB 版本是 v3.6.0。我在 Node.js 应用程序中使用猫鼬。

【问题讨论】:

  • $facet 之前添加一个$match 阶段,以限制今天和您的最高范围之间的产品。您是否总是在每个时间类别中返回固定数量的产品?只是试图理解,以便我们可以格式化它们。
  • @Veeram 我只存储最近 6 小时的价格。有时可以将新产品添加到数据库中。
  • 好的,我已经添加了答案。看看对你有没有帮助。

标签: mongodb mongoose aggregation-framework


【解决方案1】:

根据您的用例,它可能效率不高,但可以通过构面操作以以下方式合并数组。

确保所有方面类别均按名称排序,并且所有数组中的每一行都包含相同的产品。

然后,您可以先$zip 所有方面类别,然后$reduce 每个类别来组合所有不同的价格并为所有产品重复。

您可以在构面阶段之后添加以下阶段。

{"$project":{
  "data":{
    "$map":{
      "input":{"$zip":{"inputs":["$price_10s","$price_30s", "$price_30m"],"useLongestLength":true}},
      "as":"item",
      "in":{
        "$reduce":{
          "input":"$$item",
          "initialValue":{},
          "in":{"$mergeObjects":["$$this","$$value"]}
        }
      }
    }
  }
}}

【讨论】:

  • 我收到了这个错误:'$zip 在输入中找到了一个非数组表达式:“price_30m”' 代码:34468,代号:'Location34468'
  • 哦,抱歉,它应该是$price_30m 压缩包。修复
  • 我在下一条评论中发布了完整的结构。请检查一下。 @Veeram
【解决方案2】:

@Veeram,这是完整的结构。

food.aggregate( [
    {
        $facet: {
            price_now: [
                {
                    $group: {
                        _id: "$market_name",
                        price_now: {$last: "$my_time_stamp"}
                    }
                }
            ],
            price_5m: [
                {
                    $match: {
                        my_time_stamp: { "$lte": shift_5m }
                    }
                }, {
                    $group: {
                        _id: "$market_name",
                        price_5m: {$last: "$my_time_stamp"}
                    }
                }
            ],
            price_15m: [
                {
                    $match: {
                        my_time_stamp: { "$lte": shift_15m }
                    }
                }, {
                    $group: {
                        _id: "$market_name",
                        price_15m: {$last: "$my_time_stamp"}
                    }
                }
            ]
        }
    }, {
        "$project":{
            "data":{
                "$map":{
                    "input":{"$zip":{"inputs":["$price_now","$price_5m", "price_15m"],"useLongestLength":true}},
                    "as":"item",
                    "in":{
                        "$reduce":{
                            "input":"$$item",
                            "initialValue":{},
                            "in":{"$mergeObjects":["$$this","$$value"]}
                        }
                    }
                }
            }
        }
    }
], function (err, result) {
    if (err) {
         console.log(err);
    } else {
        console.log(result)
    };
});

【讨论】:

  • 试试{"$zip":{"inputs":["$price_now","$price_5m", "$price_15m"],"useLongestLength":true}}
猜你喜欢
  • 1970-01-01
  • 2021-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-26
  • 1970-01-01
  • 2013-06-09
  • 1970-01-01
相关资源
最近更新 更多