所以我有一个这样的集合:
{
id: ...,
description: {
"english": ..., // The values here are just strings
"spanish": ...,
...
},
...
}
我想查询任何描述值与给定输入匹配的文档。我知道你可以像这样查询特定的一个:
Criteria.where("description.english").is("Test")
但是我想检查所有字段,这样的事情(它不起作用):
Criteria.where("description.*").is("Test")
我也没有看到让elemMatch
工作的方法,因为值只是一个字符串而不是文档,并且没有预定义的有效键列表(这些可以是"翻译成任何语言)。
我错过了什么?
我见过this answer,但遗憾的是我无法更改收藏品。
答案 0 :(得分:1)
您可以使用AggregationExpression
($map
运营商)& AggregationOperation
($redact
阶段)在3.4
中构建以下聚合。
$objectToArray
将description
转换为键值对和$map
字符串值,并使用$in
检查test
是否在值数组中,如果在$$KEEP
阶段内匹配$$PRUNE
其他$redact
文档。
AggregationExpression mapExpression = aggregationOperationContext -> {
Map<String, Object> map = new LinkedHashMap<>();
map.put("input", new BasicDBObject("$objectToArray", "$description"));
map.put("as", "result");
map.put("in", "$$result.v");
return new BasicDBObject("$map", map);
};
AggregationOperation redactOperation = aggregationOperationContext -> {
Map<String, Object> map = new LinkedHashMap<>();
map.put("if", new BasicDBObject("$in", Arrays.asList("test", mapExpression.toDbObject(Aggregation.DEFAULT_CONTEXT))));
map.put("then", "$$KEEP");
map.put("else", "$$PRUNE");
return new BasicDBObject("$redact", new BasicDBObject("$cond", map));
};
Aggregation aggregation= Aggregation.newAggregation(redactOperation);
AggregationResults<BasicDBObject> result = mongoTemplate.aggregate(Aggregation.newAggregation(redactOperation),collection_name, BasicDBObject.class);
Shell查询供您参考:
db.collection_name.aggregate([
{
"$redact": {
"$cond": {
"if": {
"$in": [
"test",
{
"$map": {
"input": {
"$objectToArray": "$description"
},
"as": "result",
"in": "$$result.v"
}
}
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}
}
])