MongoDB查询以查找多个嵌入式文档

布拉德·梅斯

我正在尝试使用MongoDB作为通知系统的一部分来构建我的第一个非平凡查询,并且试图了解如何检查多个嵌入式文档是否符合我的条件或者根本不存在。(此外,我正在尝试使用Spring Boot Mongo api构建查询。)

我有订阅文档,其中包含以下条件映射:

{
    ...,
    criteria: [
        { key: "order.companyId", value: "ABC" },
        { key: "order.status", value: "NEW" }
    ]
}

{
    ...,
    criteria: [
        { key: "order.status", value: "NEW" }
    ]
}

{
    ...,
    criteria: [
        { key: "order.companyId", value: "ABC" }
    ]
}

当公司ABC的新订单到来时,我想生成一个与上述所有三个订阅匹配的查询。好像我需要的组合$and$elemMatch以及$in,但我无法找到如何拼凑它一起一个很好的例子。谁能给我一些有关如何入门的建议?

在最初的尝试中,我一直在生成这样的条件:Criteria.where("criteria").elemMatch(Criteria.where("key").is(key).and("value").in(value, null))但是对于同一属性,它似乎并不喜欢多个条件。


利用dsharew的建议,我现在正在使用此方法为每个键/值对建立条件列表:

private Criteria equalsOrUnspecified(String key, Object value) {
    Criteria valueMatch = Criteria.where("criteria")
            .elemMatch(Criteria.where("key").is(key).and("value").is(value));
    Criteria notSpecified = Criteria.where("criteria").not().elemMatch(Criteria.where("key").is(key));
    return new Criteria().orOperator(valueMatch, notSpecified);
}

然后结合使用

        q.addCriteria(new Criteria().andOperator(criteria.toArray(new Criteria[criteria.size()])));

但这似乎没有任何匹配。这是产生的查询之一的示例:

{ 
    "isEnabled" : true , 
    "eventType" : "order::positionUpdate" , 
    "$and" : [ 
        { "$or" : [ { "criteria" : { "$elemMatch" : { "key" : "order.bolNumber" , "value" : "51166350"}}} , { "criteria" : { "$not" : { "$elemMatch" : { "key" : "order.bolNumber"}}}}]} ,
        { "$or" : [ { "criteria" : { "$elemMatch" : { "key" : "order.consRefNumber" , "value" : "AGVS"}}} , { "criteria" : { "$not" : { "$elemMatch" : { "key" : "order.consRefNumber"}}}}]} , 
        { "$or" : [ { "criteria" : { "$elemMatch" : { "key" : "order.operationsUser.id" , "value" : "janedoe"}}} , { "criteria" : { "$not" : { "$elemMatch" : { "key" : "order.operationsUser.id"}}}}]} , 
        { "$or" : [ { "criteria" : { "$elemMatch" : { "key" : "order.bookingUser.id" , "value" : "janedoe"}}} , { "criteria" : { "$not" : { "$elemMatch" : { "key" : "order.bookingUser.id"}}}}]} , 
        { "$or" : [ { "criteria" : { "$elemMatch" : { "key" : "order.status" , "value" : "NEW"}}} , { "criteria" : { "$not" : { "$elemMatch" : { "key" : "order.status"}}}}]} , 
        { "$or" : [ { "criteria" : { "$elemMatch" : { "key" : "order.billingCustomer.id" , "value" : "EXQUOTE"}}} , { "criteria" : { "$not" : { "$elemMatch" : { "key" : "order.billingCustomer.id"}}}}]} , 
        { "$or" : [ { "criteria" : { "$elemMatch" : { "key" : "order.bookingCustomer.id" , "value" : "EXBE63A"}}} , { "criteria" : { "$not" : { "$elemMatch" : { "key" : "order.bookingCustomer.id"}}}}]} , 
        { "$or" : [ { "criteria" : { "$elemMatch" : { "key" : "order.id" , "value" : "5849005"}}} , { "criteria" : { "$not" : { "$elemMatch" : { "key" : "order.id"}}}}]} , 
        { "$or" : [ { "criteria" : { "$elemMatch" : { "key" : "companyId" , "value" : "ABC"}}} , { "criteria" : { "$not" : { "$elemMatch" : { "key" : "companyId"}}}}]}
    ]
}
布拉德·梅斯

这就是我最终需要的。criteriaMap保存事件的属性,我们要为其查找匹配的订阅。(它具有诸如“ order.bookingUser.id” =>“ janedoe”之类的映射。)如果预订未为给定属性指定值,则将其视为通配符并匹配该属性的所有值。

public Criteria createCriteria(Map<String,?> criteriaMap) {
    List<Criteria> criteria= new ArrayList<>();
    for (Map.Entry<String,Object> entry : criteriaMap) {
        list.add(equalsOrUnspecified(entry.getKey(), entry.getValue()));
    }
    return new Criteria().andOperator(criteria.toArray(new Criteria[criteria.size()]));
}

/**
 * Find a subscription where {@code key} equals {@code value}
 * or where {@code key} is not present.
 */
private void equalsOrUnspecified(String key, Object value) {
    Criteria valueMatch = Criteria.where("criteria")
            .elemMatch(Criteria.where("key").is(key).and("value").is(value));
    Criteria notSpecified = Criteria.where("criteria").not().elemMatch(Criteria.where("key").is(key));
    return new Criteria().orOperator(valueMatch, notSpecified);
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章