【问题标题】:MongoDB Query Or Condition Spring DataMongoDB 查询或条件 Spring 数据
【发布时间】:2015-08-04 19:46:01
【问题描述】:

我有status 集合,其中有四个字段abc, xyz, status, time

我想为下面的 MySql 查询创建 MongoDB 查询:

select * from status where abc = false and xyz = true and (status = pending or (status = inprogress and time = "2015-08-04"))

基本上status 可以是pendinginprogress,但如果是inprogress,则必须比较time

我尝试在 MongodDB 下创建查询,但没有成功

db.status.find
{   
    "abc" : false , 
    "xyz" : true , 
    "status" : "pending" , 
    "$and" : [ 
    { "status" : "inprogress"} , 
    { "time" : { "$eq" : { "$date" : "2015-08-04"}}}
    ]
}

我正在使用 Spring MongoDB,如果有人可以指导我如何在 Spring Data MongoDb 中创建它,我将不胜感激。

谢谢

【问题讨论】:

    标签: mongodb spring-data mongodb-query spring-data-mongodb


    【解决方案1】:

    您正在尝试的当前查询存在一些问题。首先要了解的是,除非另有说明,否则所有操作都是隐含的和“AND”条件。因此,您在此处缺少的 $or 条件必须包含状态测试的“两者”和其他组合的“时间”条件,如下所示:

    db.status.find({   
        "abc" : false, 
        "xyz" : true, 
        "$or" : [ 
            { "status" : "pending" },
            { 
               "status" : "inprogress"
               "time" : "2015-08-04"
            }
        ]
    })
    

    您在此处的 SQL 表示还暗示“时间”实际上是一个字符串。如果它已经以相同的方式存储在您的 MongoDB 文档中,那么上面的内容就可以了。如果不是,并且这些值已转换为 BSON 中的实际 Date 对象,那么您必须提供 BSON 日期(或转换的内容)作为参数。通常日期不是“精确的”,因此您可以使用“范围”来代替:

    db.status.find({   
        "abc" : false, 
        "xyz" : true, 
        "$or" : [ 
            { "status" : "pending" },
            { 
               "status" : "inprogress"
               "time" : { "$gte": new Date("2015-08-04"), "$lt": new Date("2015-08-05") }
            }
        ]
    })
    

    对于春季翻译,应该是:

    Query query = new Query(Criteria.where("abc").is(false)
        .and("xyz").is(true)
        .orOperator(
            Criteria.where("status").is("pending"),
            Criteria.where("status").is("inprogress")
                .and("time").is("2015-08-04")
        )
    );
    

    或者使用真实的日期对象和范围:

    DateTime startDay = new DateTime(2015, 8, 4, 0, 0, DateTimeZone.UTC);
    Date startDate = startDay.toDate();
    Date endDate = startDay.plusDays(1).toDate();
    
    Query query = new Query(Criteria.where("abc").is(false)
        .and("xyz").is(true)
        .orOperator(
            Criteria.where("status").is("pending"),
            Criteria.where("status").is("inprogress")
                .and("time").gte(startDate).lt(endDate)
        )
    );
    

    至少从记忆中应该是正确的,因为现在远离 IDE。还要注意这里运算符的“链接”,例如 $gte$lt 也意味着分配给同一键的值的“AND”条件。

    在处理日期时,底层驱动程序希望所有与 BSON 日期匹配的输入都被转换为 java.util.Date 类型,无论您如何实例化日期。

    【讨论】:

    • 谢谢,这就是我想要的。还有一个问题:如果我的status 文档中没有xyzstatustime 字段怎么办,我仍然想根据abc 字段获取文档。我如何在 Spring Data MongoDB 中做到这一点?
    • @Nitesh 如果您还有其他问题,那么ask another question 因为这是清楚地表达您的问题的最佳方式。使用 $exists 运算符对存在的字段进行测试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-04
    相关资源
    最近更新 更多