MongoDb,同等产品除外
我有一个问题,是关于我在试图对文档集合使用$setDifference时遇到的一个问题 我想要的是根目录1中包含的所有文档,并根据“reference.id”删除根目录2中也包含的所有文档 我的集合表示两个树结构,基本上如下所示:MongoDb,同等产品除外,mongodb,except,set-theory,set-difference,Mongodb,Except,Set Theory,Set Difference,我有一个问题,是关于我在试图对文档集合使用$setDifference时遇到的一个问题 我想要的是根目录1中包含的所有文档,并根据“reference.id”删除根目录2中也包含的所有文档 我的集合表示两个树结构,基本上如下所示: /* Tree Root 1 */ { "_id" : LUUID("9f3a73df-bca7-48b7-b111-285359e50a02"), "name" : "Root 1", "children" : [ LUUI
/* Tree Root 1 */
{
"_id" : LUUID("9f3a73df-bca7-48b7-b111-285359e50a02"),
"name" : "Root 1",
"children" : [
LUUID("ca01f1ab-7c32-4e6b-a07a-e0ee9d8ec5ac"),
LUUID("6dd8c8ed-4a60-41ca-abf1-a4d795a0c213")
]
},
/* Child 1 - Root 1 */
{
"_id" : LUUID("ca01f1ab-7c32-4e6b-a07a-e0ee9d8ec5ac"),
"parentId" : LUUID("9f3a73df-bca7-48b7-b111-285359e50a02"),
"reference" : {
"type" : "someType",
"id" : LUUID("331503FB-C4D1-4F7A-A461-933C701EF9AB")
},
"rootReferenceId" : LUUID("9f3a73df-bca7-48b7-b111-285359e50a02"),
"name" : "Child 1 (Root 1)"
}
/* Child 2 - Root 1 */
{
"_id" : LUUID("6dd8c8ed-4a60-41ca-abf1-a4d795a0c213"),
"parentId" : LUUID("9f3a73df-bca7-48b7-b111-285359e50a02"),
"reference" : {
"type" : "someType",
"id" : LUUID("23E8B540-3EFB-455A-AA5C-2B67D6B59943")
},
"rootReferenceId" : LUUID("9f3a73df-bca7-48b7-b111-285359e50a02"),
"displayName" : "Child 2 (Root 1)"
}
/* Tree Root 2 */
{
"_id" : LUUID("27f2b4a6-5471-406a-a39b-1e0b0f8c4eb9"),
"name" : "Root 2",
"children" : [
LUUID("ad4ad076-322e-4c26-8855-91c9b1912d1f"),
LUUID("66452420-dd2f-4d27-91c9-78bd0990817c")
]
},
/* Child 1 - Root 2 */
{
"_id" : LUUID("ad4ad076-322e-4c26-8855-91c9b1912d1f"),
"parentId" : LUUID("27f2b4a6-5471-406a-a39b-1e0b0f8c4eb9"),
"reference" : {
"type" : "someType",
"id" : LUUID("331503FB-C4D1-4F7A-A461-933C701EF9AB")
},
"rootReferenceId" : LUUID("27f2b4a6-5471-406a-a39b-1e0b0f8c4eb9"),
"displayName" : "Child 1 (Root 2)"
}
db.getCollection('test').aggregate([
{
$match: {
rootReferenceId: { $ne: null }
}
},
{
$group: {
_id: "$rootReferenceId",
referenceIds: { $addToSet: "$reference.id" }
}
}
])
{
LUUID("27f2b4a6-5471-406a-a39b-1e0b0f8c4eb9") : [
LUUID("331503fb-c4d1-4f7a-a461-933c701ef9ab")
]
LUUID("9f3a73df-bca7-48b7-b111-285359e50a02") : [
LUUID("23e8b540-3efb-455a-aa5c-2b67d6b59943"),
LUUID("331503fb-c4d1-4f7a-a461-933c701ef9ab")
]
}
这意味着最终我希望得到文件:
/* Child 2 - Root 1 */
{
"_id" : LUUID("6dd8c8ed-4a60-41ca-abf1-a4d795a0c213"),
"parentId" : LUUID("9f3a73df-bca7-48b7-b111-285359e50a02"),
"reference" : {
"type" : "someType",
"id" : LUUID("23E8B540-3EFB-455A-AA5C-2B67D6B59943")
},
"rootReferenceId" : LUUID("9f3a73df-bca7-48b7-b111-285359e50a02"),
"displayName" : "Child 2 (Root 1)"
}
因为它的reference.id包含在根1中,但不包含在根2中(因此它不会像子1一样从结果集中排除)
我已经编写了一个聚合阶段来对“reference.id”进行分组,如下所示:
/* Tree Root 1 */
{
"_id" : LUUID("9f3a73df-bca7-48b7-b111-285359e50a02"),
"name" : "Root 1",
"children" : [
LUUID("ca01f1ab-7c32-4e6b-a07a-e0ee9d8ec5ac"),
LUUID("6dd8c8ed-4a60-41ca-abf1-a4d795a0c213")
]
},
/* Child 1 - Root 1 */
{
"_id" : LUUID("ca01f1ab-7c32-4e6b-a07a-e0ee9d8ec5ac"),
"parentId" : LUUID("9f3a73df-bca7-48b7-b111-285359e50a02"),
"reference" : {
"type" : "someType",
"id" : LUUID("331503FB-C4D1-4F7A-A461-933C701EF9AB")
},
"rootReferenceId" : LUUID("9f3a73df-bca7-48b7-b111-285359e50a02"),
"name" : "Child 1 (Root 1)"
}
/* Child 2 - Root 1 */
{
"_id" : LUUID("6dd8c8ed-4a60-41ca-abf1-a4d795a0c213"),
"parentId" : LUUID("9f3a73df-bca7-48b7-b111-285359e50a02"),
"reference" : {
"type" : "someType",
"id" : LUUID("23E8B540-3EFB-455A-AA5C-2B67D6B59943")
},
"rootReferenceId" : LUUID("9f3a73df-bca7-48b7-b111-285359e50a02"),
"displayName" : "Child 2 (Root 1)"
}
/* Tree Root 2 */
{
"_id" : LUUID("27f2b4a6-5471-406a-a39b-1e0b0f8c4eb9"),
"name" : "Root 2",
"children" : [
LUUID("ad4ad076-322e-4c26-8855-91c9b1912d1f"),
LUUID("66452420-dd2f-4d27-91c9-78bd0990817c")
]
},
/* Child 1 - Root 2 */
{
"_id" : LUUID("ad4ad076-322e-4c26-8855-91c9b1912d1f"),
"parentId" : LUUID("27f2b4a6-5471-406a-a39b-1e0b0f8c4eb9"),
"reference" : {
"type" : "someType",
"id" : LUUID("331503FB-C4D1-4F7A-A461-933C701EF9AB")
},
"rootReferenceId" : LUUID("27f2b4a6-5471-406a-a39b-1e0b0f8c4eb9"),
"displayName" : "Child 1 (Root 2)"
}
db.getCollection('test').aggregate([
{
$match: {
rootReferenceId: { $ne: null }
}
},
{
$group: {
_id: "$rootReferenceId",
referenceIds: { $addToSet: "$reference.id" }
}
}
])
{
LUUID("27f2b4a6-5471-406a-a39b-1e0b0f8c4eb9") : [
LUUID("331503fb-c4d1-4f7a-a461-933c701ef9ab")
]
LUUID("9f3a73df-bca7-48b7-b111-285359e50a02") : [
LUUID("23e8b540-3efb-455a-aa5c-2b67d6b59943"),
LUUID("331503fb-c4d1-4f7a-a461-933c701ef9ab")
]
}
是什么让我回想起这个:
/* 1 */
{
"_id" : LUUID("27f2b4a6-5471-406a-a39b-1e0b0f8c4eb9"),
"referenceIds" : [
LUUID("331503fb-c4d1-4f7a-a461-933c701ef9ab")
]
}
/* 2 */
{
"_id" : LUUID("9f3a73df-bca7-48b7-b111-285359e50a02"),
"referenceIds" : [
LUUID("23e8b540-3efb-455a-aa5c-2b67d6b59943"),
LUUID("331503fb-c4d1-4f7a-a461-933c701ef9ab")
]
}
有人知道我如何将$setDifference转换成$setDifference接受的格式吗
我认为它应该是这样的:
/* Tree Root 1 */
{
"_id" : LUUID("9f3a73df-bca7-48b7-b111-285359e50a02"),
"name" : "Root 1",
"children" : [
LUUID("ca01f1ab-7c32-4e6b-a07a-e0ee9d8ec5ac"),
LUUID("6dd8c8ed-4a60-41ca-abf1-a4d795a0c213")
]
},
/* Child 1 - Root 1 */
{
"_id" : LUUID("ca01f1ab-7c32-4e6b-a07a-e0ee9d8ec5ac"),
"parentId" : LUUID("9f3a73df-bca7-48b7-b111-285359e50a02"),
"reference" : {
"type" : "someType",
"id" : LUUID("331503FB-C4D1-4F7A-A461-933C701EF9AB")
},
"rootReferenceId" : LUUID("9f3a73df-bca7-48b7-b111-285359e50a02"),
"name" : "Child 1 (Root 1)"
}
/* Child 2 - Root 1 */
{
"_id" : LUUID("6dd8c8ed-4a60-41ca-abf1-a4d795a0c213"),
"parentId" : LUUID("9f3a73df-bca7-48b7-b111-285359e50a02"),
"reference" : {
"type" : "someType",
"id" : LUUID("23E8B540-3EFB-455A-AA5C-2B67D6B59943")
},
"rootReferenceId" : LUUID("9f3a73df-bca7-48b7-b111-285359e50a02"),
"displayName" : "Child 2 (Root 1)"
}
/* Tree Root 2 */
{
"_id" : LUUID("27f2b4a6-5471-406a-a39b-1e0b0f8c4eb9"),
"name" : "Root 2",
"children" : [
LUUID("ad4ad076-322e-4c26-8855-91c9b1912d1f"),
LUUID("66452420-dd2f-4d27-91c9-78bd0990817c")
]
},
/* Child 1 - Root 2 */
{
"_id" : LUUID("ad4ad076-322e-4c26-8855-91c9b1912d1f"),
"parentId" : LUUID("27f2b4a6-5471-406a-a39b-1e0b0f8c4eb9"),
"reference" : {
"type" : "someType",
"id" : LUUID("331503FB-C4D1-4F7A-A461-933C701EF9AB")
},
"rootReferenceId" : LUUID("27f2b4a6-5471-406a-a39b-1e0b0f8c4eb9"),
"displayName" : "Child 1 (Root 2)"
}
db.getCollection('test').aggregate([
{
$match: {
rootReferenceId: { $ne: null }
}
},
{
$group: {
_id: "$rootReferenceId",
referenceIds: { $addToSet: "$reference.id" }
}
}
])
{
LUUID("27f2b4a6-5471-406a-a39b-1e0b0f8c4eb9") : [
LUUID("331503fb-c4d1-4f7a-a461-933c701ef9ab")
]
LUUID("9f3a73df-bca7-48b7-b111-285359e50a02") : [
LUUID("23e8b540-3efb-455a-aa5c-2b67d6b59943"),
LUUID("331503fb-c4d1-4f7a-a461-933c701ef9ab")
]
}
还是有一个完全不同的方法来实现这一点,我不知道
感谢您的帮助
编辑解决方案:
现在的解决方案就像dnickless建议的那样。真不错!非常感谢 您可以在mongodb3.6及更高版本中尝试以下聚合
db.getCollection('test').aggregate([
{ "$match": { "rootReferenceId": { "$ne": null }}},
{ "$group": {
"_id": "$rootReferenceId",
"referenceIds": { "$addToSet": "$reference.id" }
}},
{ "$group": {
"_id": null,
"data": {
"$push": { "k": { "$toString": "$_id" }, "v": "$referenceIds" }
}
}},
{ "$replaceRoot": { "newRoot": { "$arrayToObject": "$data" }}}
])
下面是不以字符串格式存储重复值的方法。这个解决方案的优点在于 a) 它返回您感兴趣的整个文档,因此您不需要第二次查询(如果您不需要整个文档,则只需将
$filter
运算符替换为$setDifference
位即可)
b) 它包含非常少且便宜的阶段(没有分组!),并且将利用rootReferenceId
字段上的索引(如果有我推荐的索引的话)
哇,非常感谢。但$arrayToObject似乎不接受UUID作为键值。有没有办法将它们转换为聚合中的字符串?@StefanO您使用的是哪个版本的mongodb?目前我使用的是4.0。也许我需要降级到3.6,但我希望这不重要。我已经更新了答案,请看一看,它将适用于4.0$toString不支持从UUID到字符串的转换。如果UUID和Mongodb变得更复杂一点的话,它们就不能很好地协同工作。这也很好。非常感谢您提供此解决方案!我根本不知道$facet聚合阶段。