Mongo聚合查询用于多维导航的查询

3

我有一个收集 products,其中包含如下这样的文档(即产品)(只提供相关代码):

{ "_id": "prod1", ... "colors": ["red","blue"], "size": ["S", "M"], ...}
{ "_id": "prod2", ... "colors": ["red","green"], "size": ["S", "XL"], ...}
{ "_id": "prod3", ... "colors": ["yellow","blue"], "size": ["XL", "XXL"], ...}

我希望能够提供给用户可用选择,如面向搜索的方式,展示选项名称和可用选项数量。
颜色:
red 2
blue 2
green 1
yellow 1

尺寸:

S 2
M 1
XL 2
XXL 1

如果我必须使用SQL完成这个任务,我可能需要为每个分面组运行一个查询。

SELECT colors, count(*) AS number FROM products GROUP BY colors

比第二个查询更优。
SELECT size, count(*) AS number FROM test GROUP BY sizes

如果有人选择了“红色”,那么我可能需要向每个查询添加“WHERE”子句:

WHERE colors = 'red'

有比我经验更丰富的人可以帮助我解决这个在MongoDB中的例子吗?我需要运行两个查询还是我缺少什么而只需要运行一个查询?我假设我会有大量的产品。任何帮助都将不胜感激。特别是如果有任何加速的技巧。我想一开始就把它做对,因此提出了这个问题。谢谢。


你使用的是哪个版本的MongoDB? - styvane
5个回答

3
以下是使用MongoDB聚合查询解决您问题的解决方案。以下是我的虚拟集合。
    {
        "_id" : ObjectId("584b82055855b8ea7ea29d65"),
        "colors" : [ 
            "Red", 
            "Yellow"
        ],
        "size" : [ 
            "S", 
            "M"
        ]
    }
    {
        "_id" : ObjectId("584b82185855b8ea7ea29d66"),
        "colors" : [ 
            "Red", 
            "Orange"
        ],
        "size" : [ 
            "S", 
            "XL"
        ]
    }
.
.

运行以下查询后:

    db.getCollection('products').aggregate([
    {$unwind : "$colors"},
    {$group : {
        _id : "$colors",
        "sum": {$sum : 1}
    }},
    {
        $project : {
            _id : 0,
            "color":"$_id",
            "count":"$sum"
        }
    }
])

然后输出结果为:
{
    "color" : "Green",
    "count" : 2
}
{
    "color" : "Orange",
    "count" : 1
}
{
    "color" : "Yellow",
    "count" : 2
}
{
    "color" : "Red",
    "count" : 2
}

如果您只想统计红色的值,请使用以下查询:

db.getCollection('products').aggregate([
    {$unwind : "$colors"},
    {$match : {"colors":"Red"}},
    {$group : {
        _id : "$colors",
        "sum": {$sum : 1}
    }},
    {
        $project : {
            _id : 0,
            "color":"$_id",
            "count":"$sum"
        }
    }
])

以上查询的输出为:
{
    "color" : "Red",
    "count" : 2
}

1

$unwind的神奇之处

当你需要对一个数组进行计数时,你必须先将其展开。看看这个例子:

db.products.aggregate([ { $unwind : "$colors" }] )

它会为数组中的每个项生成一行。
展开后,您可以将下一组数据传输到管道中:
db.products.aggregate([ 
{ $unwind : "$colors" }, 
{$group: { _id : "$colors", total_colors : { $sum : 1} } } 
] )

给聚合字段取一个你想要的名字 :) 大小也可以按照你需要的分组。

1
db.entry.aggregate([
{$unwind : "$size" },
{$group: { "_id" : "$size", count : { $sum : 1 } } }
]).pretty()

希望这可以帮到您,您可以根据自己的需求定制“count”字段和$unwind定义:
将输入文档中的数组字段解构为每个元素的输出文档。每个输出文档都是输入文档,其数组字段的值被该元素替换。

https://docs.mongodb.org/manual/reference/operator/aggregation/unwind/


1

在MongoDB数据库的3.4版本中实现了分面搜索。

{ $facet:
   {
      <outputField1>: [ <stage1>, <stage2>, ... ],
      <outputField2>: [ <stage1>, <stage2>, ... ],
      ...

   }
}

这是 文档链接

0
  • 使用多面向搜索(Faceted search),您可以实现所需的结果。
  • 这比使用多个$group 操作符更易读且性能更优。

    db.products.aggregate([{
                             $facet:{
                                 colors: [{ $unwind: "$colors" },{ $sortByCount: "$colors" }],
                                 sizes: [{ $unwind: "$sizes" },{ $sortByCount: "$sizes" }]
                             }
                           } 
                         ]);

结账 在mongodb中的$facet操作符


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接