2017-10-09 59 views
0

的任何值匹配所以我有一个集合,像这样: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

您可以使用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); 

壳牌查询,供您参考:

db.collection_name.aggregate([ 
    { 
    "$redact": { 
     "$cond": { 
     "if": { 
      "$in": [ 
      "test", 
      { 
       "$map": { 
       "input": { 
        "$objectToArray": "$description" 
       }, 
       "as": "result", 
       "in": "$$result.v" 
       } 
      } 
      ] 
     }, 
     "then": "$$KEEP", 
     "else": "$$PRUNE" 
     } 
    } 
    } 
])