【问题标题】:mongodb complex or/and querymongodb复杂或/和查询
【发布时间】:2023-04-11 08:52:01
【问题描述】:

所以我有一个集合来存储事件的开始和结束时间,我希望用户能够通过指定“过滤器”开始和结束时间来查询事件。查询应返回与过滤时间相交的任何事件。我以为我正确地构建了查询,但它没有返回我想要的结果。

示例数据(简化 mongo 文档以获取想法,时间为 HHMMSS):

{ ..., "start" : "050520", "end" : "051309" } //Should match
{ ..., "start" : "051125", "end" : "051925" } //Should match
{ ..., "start" : "052049", "end" : "052420" } //Should match
{ ..., "start" : "050000", "end" : "050500" }
{ ..., "start" : "052100", "end" : "052721" }

我尝试的查询是(如果我错过了括号,请原谅我,这不是问题):

find( { $or : [ 
            { start : { $gte : "050600", $lt : "052100" } }, 
            { end : { $lt : "052100", $gt : "050600" } } 
        ] } )

仅返回三个结果之一。切换 $or 部分的顺序(在开始时间之前查询结束时间)会给我两个结果,但不是全部三个。我似乎记得在应用查询的第二部分之前,对于复合查询,mongo 会丢弃与第一部分不匹配的结果,但我认为 $or 运算符会处理这个问题。 有任何想法吗?我的查询不正确吗,这是在 mongo 中查询的限制吗?

【问题讨论】:

    标签: javascript mongodb mongo-shell


    【解决方案1】:

    使用 MongoDB 2.4.5 我尝试了上述方法,并在两种情况下都返回了“应该匹配”结果的前 2 个。

    我不认为应该返回第三个,因为它需要 ("052049" >= "050600" && "052049" " 050600") 两者都不为真。

    MongoDB shell version: 2.4.5
    connecting to: test
    > 
    > db.mycol.save({ "start" : "050520", "end" : "051309" }) 
    > db.mycol.save({ "start" : "051125", "end" : "051925" })
    > db.mycol.save({ "start" : "052049", "end" : "052420" }) 
    > db.mycol.save({ "start" : "050000", "end" : "050500" })
    > db.mycol.save({ "start" : "052100", "end" : "052721" })
    >
    > db.mycol.find( 
    ... { $or : 
    ... [ { $and : [ { start : { $gte : "050600" } }, { start : { $lt : "052000" } } ] }, 
    ...   { $and : [ { end : { $lt : "052000" } }, { end : { $gt : "050600" } } ] } 
    ... ] 
    ...     } )
    { "_id" : ObjectId("520528522683a40682f12b5c"), "start" : "050520", "end" : "051309" }
    { "_id" : ObjectId("520528522683a40682f12b5d"), "start" : "051125", "end" : "051925" }
    > 
    > 
    > db.mycol.find( 
    ... { $or : 
    ... [     { $and : [ { end : { $lt : "052000" } }, { end : { $gt : "050600" } } ] } , 
    ...   { $and : [ { start : { $gte : "050600" } }, { start : { $lt : "052000" } } ] }
    ... ] 
    ...     } )
    { "_id" : ObjectId("520528522683a40682f12b5c"), "start" : "050520", "end" : "051309" }
    { "_id" : ObjectId("520528522683a40682f12b5d"), "start" : "051125", "end" : "051925" }
    > 
    

    【讨论】:

    • 哈哈,你说得对,第三个不应该匹配。嗯,我想知道,我目前正在使用 MongoDB 2.2.2,这可能是问题所在。我会尝试升级并验证。
    • 此行为在 2.2.2 和 2.4.5 之间应该是相同的。如果您发现不同,请告诉我。
    • 嗯,我升级到 2.4.5 并且它工作...所以我回到 2.2.2 并再次尝试,它在那里也按预期工作。我一定是打错了:/对不起!
    【解决方案2】:

    您的查询应该可以正常工作,但第三个不应该匹配,因为startend 都超出了范围。

    但是,您可以将查询写得更清楚、更简洁:

    db.test.find({ $or: [
        { start: { $gte: "050600", $lt : "052000" }}, 
        { end: { $lt: "052000", $gt: "050600" }}
    ]});
    

    【讨论】:

    • 噢!我希望我的过滤器包含那个结束时间,我在示例中错过了。但很高兴知道我没有意识到我可以将 gte, lt 运算符加入到一个语句中。我认为查询可能不起作用,因为我使用的是过期版本的 mongo。
    • @mike 我对此表示怀疑,因为我认为这种行为在最近的版本中没有任何改变。
    猜你喜欢
    • 2012-06-06
    • 1970-01-01
    • 2019-10-05
    • 2012-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-09
    相关资源
    最近更新 更多