【发布时间】:2019-01-17 08:24:47
【问题描述】:
如果包含某个值,我需要从 2 个单独的嵌套数组中获得 2 个总和结果,共 10 次(假设为 10 个国家/地区的产品总和数据)。我知道我需要使用聚合函数,但我不明白。
我尝试了 $facet,但在 450 万个文档(包含嵌套数组数据)中大约需要 30-40 秒才能获得结果。 (想象一下,为此我需要循环 10 次)
我尝试了以下解决方案但失败了:
How to group query with multiple $cond?
Multiple Counts with single query in mongodb
集合结构:
{
_id,
sku: 'p1',
someField,
someField2,
...
products: [
{
productid:132,
someproductfield,
someproductfield2,
...
countryId: double <- The field which is used when sum conditon
},
{
productid:451,
someproductfield,
someproductfield2,
...
countryId: double <- The field which is used when sum conditon
},
{
productid:218,
someproductfield,
someproductfield2,
...
countryId: double <- The field which is used when sum conditon
}
],
sellers: [
{
sellerid: 101001,
somesellerfield,
somesellerfield2,
...
countryId: double <- The field which is used when sum conditon
},
{
sellerid: 104201,
somesellerfield,
somesellerfield2,
...
countryId: double <- The field which is used when sum conditon
},
{
sellerid: 205401,
somesellerfield,
somesellerfield2,
...
countryId: double <- The field which is used when sum conditon
}
]
},
{
_id,
sku: 'x2',
someField,
someField2,
...
products: [
{
productid:142,
someproductfield,
someproductfield2,
...
countryId: double <- The field which is used when sum conditon
},
{
productid:71,
someproductfield,
someproductfield2,
...
countryId: double <- The field which is used when sum conditon
},
{
productid:28,
someproductfield,
someproductfield2,
...
countryId: double <- The field which is used when sum conditon
}
],
sellers: [
{
sellerid: 1001,
somesellerfield,
somesellerfield2,
...
countryId: double <- The field which is used when sum conditon
},
{
sellerid: 1421,
somesellerfield,
somesellerfield2,
...
countryId: double <- The field which is used when sum conditon
},
{
sellerid: 20501,
somesellerfield,
somesellerfield2,
...
countryId: double <- The field which is used when sum conditon
}
]
},
{
_id,
sku: 'p3',
someField,
someField2,
...
products: [
{
productid:543,
someproductfield,
someproductfield2,
...
countryId: double <- The field which is used when sum conditon
},
{
productid:52,
someproductfield,
someproductfield2,
...
countryId: double <- The field which is used when sum conditon
},
{
productid:32,
someproductfield,
someproductfield2,
...
countryId: double <- The field which is used when sum conditon
}
...
],
sellers: [
{
sellerid: 5201,
somesellerfield,
somesellerfield2,
...
countryId: double <- The field which is used when sum conditon
},
{
sellerid: 1231,
somesellerfield,
somesellerfield2,
...
countryId: double <- The field which is used when sum conditon
},
{
sellerid: 12565461,
somesellerfield,
somesellerfield2,
...
countryId: double <- The field which is used when sum conditon
}
]
}
我需要这样的结果:
{
countryId:5,
productsOnCountryCount: 10102,
/* something like count only products which has the countryId =>
$sum: { $cond: [{$eq: ['$products.countryId',2]},1,0] }
*/
unavailableProductsCount: 3560
/* something like sellers have but not available to sell or list for some
reason =>
$sum: {$cond: [{$and:[{$eq: ['$sellers.countryId',2]},{$ne:
['$products.countryId',2]}]},1,0]}
*/
}
方法和响应时间更新
var cid = 2; // assume countryId of USA
target document total = about 20 million data (including nested arrays)
方法 1 (@KevinSmith) 响应时间:48-50 秒
db.test.aggregate([
{ "$facet": {
"productsOnCountryCount": [
{ "$unwind" : "$products" },
{ "$match" : { "products.countryId": cid}},
{ "$count": "productsOnCountryCount" },
],
"unavailableProductsCount": [
{ "$match" : {"sellers.countryId": cid, "products.countryId" : { $ne: cid } } },
{ "$count": "unavailableProductsCount" }
]
}},
{ "$project": {
"productsOnCountryCount": { "$arrayElemAt": ["$productsOnCountryCount.productsOnCountryCount", 0] },
"unavailableProductsCount": { "$arrayElemAt": ["$unavailableProductsCount.unavailableProductsCount", 0] }
}}
]);
方法 2 响应时间:36-38 秒
db.test.aggregate([
{ "$facet": {
"count1": [
{ "$match" : {'products.countryId': cid }},
{ "$count": "Count" }
],
"count2": [
{ "$match" : {'sellers.countryId': cid,'products.countryId':{$ne: cid} }},
{ "$count": "Count" }
]
}}
])
方法 3 响应时间:20-21 秒
db.test.aggregate([
{$group: {
_id: null,
distct: { $sum: { $cond: [{$in: [cid,'$products.countryId']},1,0] }},
undistct: {
$sum: {
$cond: [
{$and:
[
{$in: [cid,'$sellers.countryId']},
{$not:{$in: [cid,'$products.countryId']}}
]},
1,
0
] }}
}
}
])
根据结果,我认为我会选择方法 3。 感谢所有感兴趣的人
【问题讨论】:
-
你能提供一个小的集合样本和聚合的输出你需要什么,因为我不确定你想在什么条件下求和。
-
@KevinSmith 我已经在 ineed the result like 部分中提到了它。我用条件输入了我想要的查询。问题是如何将所有这些与最佳单个查询结合起来。
-
假设 cid=3 => 查询的国家 ID。我想要的只是 $sum: { $cond: [{$eq: ['$products.countryId',cid]},1,0] } 和 $sum 的组合结果: {$cond: [{$and:[{$eq: ['$sellers.countryId',cid]},{$ne: ['$products.countryId',cid]}]},1,0]}
-
你有什么索引?