Mongodb 聚合期间围绕匹配查询对数据进行分区
我一直想弄清楚的是在mongo查询中执行某种分区(按谓词分割)。我当前的查询如下所示:Mongodb 聚合期间围绕匹配查询对数据进行分区,mongodb,mongodb-query,aggregate,partitioning,mongo-java,Mongodb,Mongodb Query,Aggregate,Partitioning,Mongo Java,我一直想弄清楚的是在mongo查询中执行某种分区(按谓词分割)。我当前的查询如下所示: db.posts.aggregate([ {"$match": { $and:[ {$or:[{"toggled":false},{"toggled":true, "status":"INACTIVE"}]} , {"updatedAt":{$gte:1549786260000}} ] }}, {"$unwind" :"$interests"}, {"$group" : {"_id": {"iid"
db.posts.aggregate([
{"$match": { $and:[ {$or:[{"toggled":false},{"toggled":true, "status":"INACTIVE"}]} , {"updatedAt":{$gte:1549786260000}} ] }},
{"$unwind" :"$interests"},
{"$group" : {"_id": {"iid": "$interests", "pid":"$publisher"}, "count": {"$sum" : 1}}},
{"$project":{ _id: 0, "iid": "$_id.iid", "pid": "$_id.pid", "count": 1 }}
])
这将产生以下输出:
{
"count" : 3.0,
"iid" : "INT456",
"pid" : "P789"
}
{
"count" : 2.0,
"iid" : "INT789",
"pid" : "P789"
}
{
"count" : 1.0,
"iid" : "INT123",
"pid" : "P789"
}
{
"count" : 1.0,
"iid" : "INT123",
"pid" : "P123"
}
到目前为止一切正常,但后来我意识到,对于匹配特定筛选器的文档,
{“toggled”:true,“status”:“INACTIVE”}
,我宁愿减少计数(-1)。(考虑到最终值也可能为负值。)
是否有一种方法可以在match
之后以某种方式对数据进行分区,以确保对两个文档集合执行不同的分组操作
听起来和我要找的相似的东西是
,或者,也许,但从文档示例中我能说的不多
注意:我可以感觉到,处理这个问题的一个简单方法是执行两个查询,但我正在寻找一个查询来执行该操作
上述输出的示例文件如下:
/* 1 */
{
"_id" : ObjectId("5d1f7******"),
"id" : "CON123",
"title" : "Game",
"content" : {},
"status" : "ACTIVE",
"toggle":false,
"publisher" : "P789",
"interests" : [
"INT456"
],
"updatedAt" : NumberLong(1582078628264)
}
/* 2 */
{
"_id" : ObjectId("5d1f8******"),
"id" : "CON456",
"title" : "Home",
"content" : {},
"status" : "INACTIVE",
"toggle":true,
"publisher" : "P789",
"interests" : [
"INT456",
"INT789"
],
"updatedAt" : NumberLong(1582078628264)
}
/* 3 */
{
"_id" : ObjectId("5d0e9******"),
"id" : "CON654",
"title" : "School",
"content" : {},
"status" : "ACTIVE",
"toggle":false,
"publisher" : "P789",
"interests" : [
"INT123",
"INT456",
"INT789"
],
"updatedAt" : NumberLong(1582078628264)
}
/* 4 */
{
"_id" : ObjectId("5d207*******"),
"id" : "CON789",
"title":"Stack",
"content" : { },
"status" : "ACTIVE",
"toggle":false,
"publisher" : "P123",
"interests" : [
"INT123"
],
"updatedAt" : NumberLong(1582078628264)
}
但我期待的结果是
{
"count" : 1.0, (2-1)
"iid" : "INT456",
"pid" : "P789"
}
{
"count" : 0.0, (1-1)
"iid" : "INT789",
"pid" : "P789"
}
{
"count" : 1.0,
"iid" : "INT123",
"pid" : "P789"
}
{
"count" : 1.0,
"iid" : "INT123",
"pid" : "P123"
}
此聚合提供了所需的结果
db.posts.aggregate( [
{ $match: { updatedAt: { $gte: 1549786260000 } } },
{ $facet: {
FALSE: [
{ $match: { toggle: false } },
{ $unwind : "$interests" },
{ $group : { _id : { iid: "$interests", pid: "$publisher" }, count: { $sum : 1 } } },
],
TRUE: [
{ $match: { toggle: true, status: "INACTIVE" } },
{ $unwind : "$interests" },
{ $group : { _id : { iid: "$interests", pid: "$publisher" }, count: { $sum : -1 } } },
]
} },
{ $project: { result: { $concatArrays: [ "$FALSE", "$TRUE" ] } } },
{ $unwind: "$result" },
{ $replaceRoot: { newRoot: "$result" } },
{ $group : { _id : "$_id", count: { $sum : "$count" } } },
{ $project:{ _id: 0, iid: "$_id.iid", pid: "$_id.pid", count: 1 } }
] )
[编辑和添加]
使用问题帖子中的输入数据进行查询的输出:
{ "count" : 1, "iid" : "INT123", "pid" : "P789" }
{ "count" : 1, "iid" : "INT123", "pid" : "P123" }
{ "count" : 0, "iid" : "INT789", "pid" : "P789" }
{ "count" : 1, "iid" : "INT456", "pid" : "P789" }
[编辑和添加2]
此查询使用不同的方法(代码)获得相同的结果:
[编辑和添加3]
注意:
facet查询在同一组文档上运行两个facet(TRUE和FALSE);这就像两个并行运行的查询。但是,为了获得所需的输出,还存在一些代码重复和额外的阶段,用于在管道中形成文档
第二个查询避免了代码重复,聚合管道中的阶段要小得多。当输入数据集有大量文档要处理时,这将产生不同的性能。一般来说,较小的阶段意味着文档的迭代次数较少(因为一个阶段必须扫描从上一级输出的文档)。您可以尝试使用流水线级。@ PrasADy:考虑回答吗?同时,我会按照whoami的要求,用示例文档更新这个问题。我使用facets发布了一个答案。但是,稍后我可能会进一步细化它并更新查询(在代码方面,而不是函数方面)。我发布了错误版本的代码。我将答案更新为正确答案。我添加了具有相同结果的代码的另一个版本。这个不使用facet。更新的查询可以工作。我会花更多的时间学习方面
。与正常的匹配
、放松
、组
和项目
流程相比,是否存在任何性能影响?请检查我的新版本代码;它比第一个版本有效。对于未指定的情况,“default”:0
可以。此外,它是文档。
db.posts.aggregate( [
{
$match: { updatedAt: { $gte: 1549786260000 } }
},
{
$unwind : "$interests"
},
{
$group : {
_id : {
iid: "$interests",
pid: "$publisher"
},
count: {
$sum: {
$switch: {
branches: [
{ case: { $eq: [ "$toggle", false ] },
then: 1 },
{ case: { $and: [ { $eq: [ "$toggle", true] }, { $eq: [ "$status", "INACTIVE" ] } ] },
then: -1 }
]
}
}
}
}
},
{
$project:{
_id: 0,
iid: "$_id.iid",
pid: "$_id.pid",
count: 1
}
}
] )