数组元素上的 mongocollection 过滤器
mongocollection filter on array elements
我有一个结构如下的文档
{
"id" : "abcdefg",
"sub" : {"field1" : "value1", "field3" : "value3"},
"profile" : {
"array" : [
{"score" : 1},
{"score" : 2},
{"score" : 3}
]
}
}
我想过滤 profile.score.score,我使用以下
Document idQuery = new Document("id", new Document("$in", ids));
// ids is an array of id
Document idMatch = new Document("$match", idQuery);
Document projectArray = new Document("$project", new Document("id",1).append("profile.array", 1).append("sub", 1));
Document unwindArray = new Document("$unwind", "$profile.array");
Document filterQuery = new Document("profile.array.score", new Document("$gte", 2));
Document filterMatch = new Document("$match", filterQuery);
Document groupResult = new Document("$group", new Document("_id", "$id").append("array", new Document("$push", "$profile.array")).append("sub", new Document("$push", "$sub")));
List<Document> pipeLineList = new ArrayList<Document>();
pipeLineList.add(idMatch);
pipeLineList.add(projectArray);
pipeLineList.add(unwindArray);
pipeLineList.add(filterMatch);
pipeLineList.add(groupResult);
AggregateIterable<Document> result = companyProfiles.aggregate(pipeLineList);
通过以上操作,我得到了
的结果
{
"id" : "abcdefg",
"sub" : [
{"field1" : "value1", "field3" : "value3"},
{"field1" : "value1", "field3" : "value3"}
]
"profile" : {
"array" : [
{"score" : 2},
{"score" : 3}
]
}
}
子字段作为数组中的元素插入了两次,这不是我想要的。我应该怎么做才能得到正确的结果
{
"id" : "abcdefg",
"sub" : {"field1" : "value1", "field3" : "value3"},
"profile" : {
"array" : [
{"score" : 2},
{"score" : 3}
]
}
}
将您的 $group
阶段更改为使用 $first
而不是 $push
以避免重复。
Document groupResult = new Document("$group", new Document("_id", "$id").append("array", new Document("$push", "$profile.array")).append("sub", new Document("$first", "$sub")));
或者,您可以重构代码以使用 $filter
替换 $unwind
+ $match
+ $group
.
Document idQuery = new Document("id", new Document("$in", ids));
Document idMatch = new Document("$match", idQuery);
Document filterQuery = new Document("$gte", Arrays.asList("$$profilearray.score", 2));
Document filterArray = new Document("$filter", new Document("input", "$profile.array").append("as", "profilearray").append("cond", filterQuery));
Document projectArray = new Document("$project", new Document("id",1).append("profile.array", filterArray).append("sub", 1));
List<Document> pipeLineList = new ArrayList<Document>();
pipeLineList.add(idMatch);
pipeLineList.add(projectArray);
我有一个结构如下的文档
{
"id" : "abcdefg",
"sub" : {"field1" : "value1", "field3" : "value3"},
"profile" : {
"array" : [
{"score" : 1},
{"score" : 2},
{"score" : 3}
]
}
}
我想过滤 profile.score.score,我使用以下
Document idQuery = new Document("id", new Document("$in", ids));
// ids is an array of id
Document idMatch = new Document("$match", idQuery);
Document projectArray = new Document("$project", new Document("id",1).append("profile.array", 1).append("sub", 1));
Document unwindArray = new Document("$unwind", "$profile.array");
Document filterQuery = new Document("profile.array.score", new Document("$gte", 2));
Document filterMatch = new Document("$match", filterQuery);
Document groupResult = new Document("$group", new Document("_id", "$id").append("array", new Document("$push", "$profile.array")).append("sub", new Document("$push", "$sub")));
List<Document> pipeLineList = new ArrayList<Document>();
pipeLineList.add(idMatch);
pipeLineList.add(projectArray);
pipeLineList.add(unwindArray);
pipeLineList.add(filterMatch);
pipeLineList.add(groupResult);
AggregateIterable<Document> result = companyProfiles.aggregate(pipeLineList);
通过以上操作,我得到了
的结果{
"id" : "abcdefg",
"sub" : [
{"field1" : "value1", "field3" : "value3"},
{"field1" : "value1", "field3" : "value3"}
]
"profile" : {
"array" : [
{"score" : 2},
{"score" : 3}
]
}
}
子字段作为数组中的元素插入了两次,这不是我想要的。我应该怎么做才能得到正确的结果
{
"id" : "abcdefg",
"sub" : {"field1" : "value1", "field3" : "value3"},
"profile" : {
"array" : [
{"score" : 2},
{"score" : 3}
]
}
}
将您的 $group
阶段更改为使用 $first
而不是 $push
以避免重复。
Document groupResult = new Document("$group", new Document("_id", "$id").append("array", new Document("$push", "$profile.array")).append("sub", new Document("$first", "$sub")));
或者,您可以重构代码以使用 $filter
替换 $unwind
+ $match
+ $group
.
Document idQuery = new Document("id", new Document("$in", ids));
Document idMatch = new Document("$match", idQuery);
Document filterQuery = new Document("$gte", Arrays.asList("$$profilearray.score", 2));
Document filterArray = new Document("$filter", new Document("input", "$profile.array").append("as", "profilearray").append("cond", filterQuery));
Document projectArray = new Document("$project", new Document("id",1).append("profile.array", filterArray).append("sub", 1));
List<Document> pipeLineList = new ArrayList<Document>();
pipeLineList.add(idMatch);
pipeLineList.add(projectArray);