嵌入式文档的$divide元素 - MongoDB 聚合



我正在尝试创建一个聚合MongoDB查询。

数据结构:

{
"object_name": Example,
"values": [ {"name":"value1", "value":1}, 
{"name":"value2", "value":10},
{"name":"total", "value":105}
}

目标: 查找value1/total > 0.5value2/total > 0.25total > 100的对象名称。 数据的结构以这种方式提供value_name和值字段的索引。

我尝试了什么 - 使用以下管道聚合:

$match:过滤总> 100 的文档:

$match: { values: { $elemMatch: { value_name: "total", value: {$gte: 100 }

$project:只抓取我们需要的value_names(有近200个不同的名字(

$project: {
values: {
$filter: {
input: "$values",
as: "value",
cond: { $or: [
{ $eq: [ "$$value.name", "name1"] },
{ $eq: [ "$$value.name", "name2"] },
{ $eq: [ "$$value.name", "total"] },
] }
}
},
name: 1
}

然后,{ $unwind: "$values" }

在这里,我可以$group$divide: name1/total, name2/total但是我被困在如何获得这些值上。 我不能简单地做stats.value:因为它不知道我指的是哪个值。我相信$group不能$elemMatch也匹配这个名字。

如果有更简单的解决方案,我将非常感谢您的意见。

请尝试以下操作:

  1. 我们正在过滤值数组包含对象的文档name : totalvalue > 100.
  2. 使用name : total添加对象 来记录。
  3. 仅保留与条件匹配的对象 在值数组中value1/total > 0.5value2/total > 0.25
  4. 如果 该数组的大小大于1,则这两个条件是 遇到。
  5. 最后只投影object_name

查询:

db.yourCollectionName.aggregate([{ $match: { values: { $elemMatch: { name: "total", value: { $gte: 100 } } } } }, 
{
$addFields: {
totalValue: {
$arrayElemAt: [{
$filter: {
input: "$values",
as: "item",
cond: { $eq: ["$$item.name", 'total'] }
}
}, 0]
}
}
},
{
$project: {
values: {
$filter: {
input: "$values",
as: "value",
cond: {
$or: [
{ $cond: [{ $eq: ["$$value.name", "value1"] }, { $gt: [{ $divide: ["$$value.value", '$totalValue.value'] }, 0.5] }, false] },
{ $cond: [{ $eq: ["$$value.name", "value2"] }, { $gt: [{ $divide: ["$$value.value", '$totalValue.value'] }, 0.25] }, false] }
]
}
}
}, object_name: 1
}
}, {
$match: {
$expr: { $gt: [{ $size: "$values" }, 1] }
}
}, { $project: { object_name: 1, _id: 0 } }])

收集数据 :

/* 1 */
{
"_id" : ObjectId("5e20bd94d02e05b694d55fa5"),
"object_name" : "Example",
"values" : [ 
{
"name" : "value1",
"value" : 1
}, 
{
"name" : "value2",
"value" : 10
}, 
{
"name" : "total",
"value" : 105
}, 
{
"name" : "total1",
"value" : 105
}
]
}
/* 2 */
{
"_id" : ObjectId("5e20bdb1d02e05b694d56490"),
"object_name" : "Example2",
"values" : [ 
{
"name" : "value1",
"value" : 1
}, 
{
"name" : "value2",
"value" : 10
}, 
{
"name" : "total",
"value" : 5
}, 
{
"name" : "total1",
"value" : 5
}
]
}
/* 3 */
{
"_id" : ObjectId("5e20d1b7d02e05b694d7c57a"),
"object_name" : "Example3",
"values" : [ 
{
"name" : "value1",
"value" : 100
}, 
{
"name" : "value2",
"value" : 100
}, 
{
"name" : "total",
"value" : 200
}, 
{
"name" : "total1",
"value" : 205
}
]
}
/* 4 */
{
"_id" : ObjectId("5e20d1cad02e05b694d7c71c"),
"object_name" : "Example4",
"values" : [ 
{
"name" : "value1",
"value" : 200
}, 
{
"name" : "value2",
"value" : 40
}, 
{
"name" : "total",
"value" : 200
}, 
{
"name" : "total1",
"value" : 205
}
]
}
/* 5 */
{
"_id" : ObjectId("5e20d1e2d02e05b694d7c933"),
"object_name" : "Example5",
"values" : [ 
{
"name" : "value1",
"value" : 150
}, 
{
"name" : "value2",
"value" : 100
}, 
{
"name" : "total",
"value" : 200
}, 
{
"name" : "total1",
"value" : 205
}
]
}

结果:

/* 1 */
{
"object_name" : "Example5"
}

您可以使用运算符将数组转换为$arrayToObject对象并添加tmp字段以轻松访问value1value2total

db.collection.aggregate([
{
$addFields: {
tmp: {
$arrayToObject: {
$map: {
input: "$values",
as: "value",
in: {
k: "$$value.name",
v: "$$value.value"
}
}
}
},
name: 1
}
},
{
$match: {
$expr: {
$and: [
{
$gt: [
{
$divide: [
"$tmp.value1",
"$tmp.total"
]
},
0.5
]
},
{
$gt: [
{
$divide: [
"$tmp.value2",
"$tmp.total"
]
},
0.25
]
},
{
$gt: [
"$tmp.total",
100
]
}
]
}
}
},
{
$project: {
tmp: 0
}
}
])

蒙戈游乐场

最新更新