Mongodb:考虑到嵌套值,需要聚合并执行重复数据消除
我希望在mongodb中执行一个聚合,它可以根据包含集合的嵌套字段中的值来告诉我哪些文档具有重复匹配。我正在处理的文档的简化如下所示Mongodb:考虑到嵌套值,需要聚合并执行重复数据消除,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我希望在mongodb中执行一个聚合,它可以根据包含集合的嵌套字段中的值来告诉我哪些文档具有重复匹配。我正在处理的文档的简化如下所示 { "field":"some value", "emails":[ { "emailAddress":"example@testing.com" } } 为了消除重复数据,我需要执行一个聚合,该聚合可以告诉我集合中共享相同电子邮件地址的所有文档。明确地说,我的意思是收集所有至少有一个共享电
{
"field":"some value",
"emails":[
{
"emailAddress":"example@testing.com"
}
}
为了消除重复数据,我需要执行一个聚合,该聚合可以告诉我集合中共享相同电子邮件地址的所有文档。明确地说,我的意思是收集所有至少有一个共享电子邮件地址值的附带文档的文档,而不是本示例文档。非常感谢您的帮助。(OP扩展了问题)
因此,给定一些如下输入数据:
var d = [
{ "fld":"X", "emails":[ {"emailAddress":"example@testing.com"} ]}
,{ "fld":"Y", "emails":[ {"emailAddress":"example2@testing.com"} ]}
,{ "fld":-5, "emails":[ {"emailAddress":"example@testing.com"}, {"emailAddress":"a@b.com"} ]}
,{ "emails":[ {"emailAddress":"a@b.com"}, {"emailAddress":"corn@dog.com"} ]}
,{ "emails":[ {"emailAddress":"zip@b.com"}, {"emailAddress":"corn@dog.com"} ]}
,{ "fld":"Q", "emails":[ {"emailAddress":"zzz@b.com"}, {"emailAddress":"a@b.com"} ]}
];
这就成功了$match
在存在fld
时,无论值的类型如何,都有效。您不必排除其他字段(仅通过$projecting
电子邮件),但这会减少通过管道流动的多余/不需要的数据
db.foo.aggregate([
{$match: {"fld": {$exists: true}} // only process docs where field fld exists
,{$project: {"emails":1}}
,{$unwind: "$emails"}
,{$group: {_id:"$emails.emailAddress", n:{$sum:1}, docs: {$push: "$_id"}}}
,{$match: {n: {$gt:1}}}
]);
这将产生:
{
"_id" : "a@b.com",
"n" : 2,
"docs" : [
ObjectId("59d2d69274d1e2d00ebec06f"),
ObjectId("59d2d69274d1e2d00ebec072")
]
}
{
"_id" : "example@testing.com",
"n" : 2,
"docs" : [
ObjectId("59d2d69274d1e2d00ebec06d"),
ObjectId("59d2d69274d1e2d00ebec06f")
]
}
(OP扩大了问题)
因此,给定一些如下输入数据:
var d = [
{ "fld":"X", "emails":[ {"emailAddress":"example@testing.com"} ]}
,{ "fld":"Y", "emails":[ {"emailAddress":"example2@testing.com"} ]}
,{ "fld":-5, "emails":[ {"emailAddress":"example@testing.com"}, {"emailAddress":"a@b.com"} ]}
,{ "emails":[ {"emailAddress":"a@b.com"}, {"emailAddress":"corn@dog.com"} ]}
,{ "emails":[ {"emailAddress":"zip@b.com"}, {"emailAddress":"corn@dog.com"} ]}
,{ "fld":"Q", "emails":[ {"emailAddress":"zzz@b.com"}, {"emailAddress":"a@b.com"} ]}
];
这就成功了$match
在存在fld
时,无论值的类型如何,都有效。您不必排除其他字段(仅通过$projecting
电子邮件),但这会减少通过管道流动的多余/不需要的数据
db.foo.aggregate([
{$match: {"fld": {$exists: true}} // only process docs where field fld exists
,{$project: {"emails":1}}
,{$unwind: "$emails"}
,{$group: {_id:"$emails.emailAddress", n:{$sum:1}, docs: {$push: "$_id"}}}
,{$match: {n: {$gt:1}}}
]);
这将产生:
{
"_id" : "a@b.com",
"n" : 2,
"docs" : [
ObjectId("59d2d69274d1e2d00ebec06f"),
ObjectId("59d2d69274d1e2d00ebec072")
]
}
{
"_id" : "example@testing.com",
"n" : 2,
"docs" : [
ObjectId("59d2d69274d1e2d00ebec06d"),
ObjectId("59d2d69274d1e2d00ebec06f")
]
}
这是一个非常好的回复,谢谢。简短的后续问题,如果我想确保这些结果中只包含包含特定字段的文档,我将如何应用该类型的筛选器?@mmarbles特定字段(即文档中存在字段名)或字段的特定值?前者是特定字段。@mrmarbles示例已修改;看上面这是一个很好的回复,谢谢。简短的后续问题,如果我想确保这些结果中只包含包含特定字段的文档,我将如何应用该类型的筛选器?@mmarbles特定字段(即文档中存在字段名)或字段的特定值?前者是特定字段。@mrmarbles示例已修改;见上文