Spring MongoDB - 匹配子文档

时间:2017-10-09 21:53:13

标签: spring mongodb

所以我有一个这样的集合:

{
    id: ...,
    description: {
        "english": ...,  // The values here are just strings
        "spanish": ...,
        ...
    },
    ...
}

我想查询任何描述值与给定输入匹配的文档。我知道你可以像这样查询特定的一个:

Criteria.where("description.english").is("Test")

但是我想检查所有字段,这样的事情(它不起作用):

Criteria.where("description.*").is("Test")

我也没有看到让elemMatch工作的方法,因为值只是一个字符串而不是文档,并且没有预定义的有效键列表(这些可以是"翻译成任何语言)。

我错过了什么?

我见过this answer,但遗憾的是我无法更改收藏品。

1 个答案:

答案 0 :(得分:1)

您可以使用AggregationExpression$map运营商)& AggregationOperation$redact阶段)在3.4中构建以下聚合。

$objectToArraydescription转换为键值对和$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"
      }
    }
  }
])