【问题标题】:Search multiple fields for multiple values in MongoDB在 MongoDB 中搜索多个字段的多个值
【发布时间】:2014-01-28 21:53:22
【问题描述】:

我有一个 MongoDB 集合,其中特定字符串可能出现在多个字段中的任何一个中:

{"_id":1, "field1": "foo", "field2": "bar", "field3": "baz", "otherfield": "stuff"},
{"_id":2, "field1": "bar", "field2": "baz", "field3": "foo", "otherfield": "morestuff"},
{"_id":3, "field1": "baz", "field2": "foo", "field3": "bar", "otherfield": "you get the idea"}

我需要查询,以便返回所有记录,其中一组字段中的任何一个等于数组中的任何值...基本上,如果我有 ["foo","bar"] 我需要它来匹配其中任何一个字符串在 field1 或 field2 中(但不在任何其他字段中)。

显然我可以通过一系列多个查询来做到这一点

db.collection.find({"field1":{"$in":["foo","bar"]}}) db.collection.find({"field2":{"$in":["foo","bar"]}})

等等,我还做了一个非常大的 $or 查询将它们连接在一起,但它似乎效率太低(我的实际集合需要匹配可能出现在 9 个字段中的任何一个中的 15 个字符串中的任何一个) ...但我对 nosql 数据库仍然很陌生,并且不确定我需要在这里使用的最佳范例。非常感谢任何帮助。

【问题讨论】:

    标签: arrays mongodb


    【解决方案1】:

    试试

    db.collection.find(
        // Find documents matching any of these values
        {$or:[
            {"field1":{"$in":["foo","bar"]}},
            {"field2":{"$in":["foo","bar"]}}
        ]}
    )
    

    也可以参考这个question

    【讨论】:

    • jlmcdonald 说他试图将查询连接到一个大的 $​​or 查询...
    • 对……这行得通,但必须有比这更有效的方法。
    • 您的意思是高效...一种高效的编写方式...或 mongo 执行该查询的高效方式...
    • 这是一个很好的问题......正如我所提到的,我在 9 个字段中的任何一个中都有 15 个字符串,所以它在编写时看起来很丑陋 $or 查询,所以有一些更具可读性将是一个小好处。但我最担心的是数据库的费用。我假设一个连接的 $or 查询正在执行每个查询,然后聚合结果,但也许这是错误的并且 $or 不是非常昂贵?
    • 就外观而言,我不知道更好的查询方式以使查询看起来更好......但至于数据库的费用,所有这些连接/过滤/联合查询在 @ 内使用987654323@ 被称为Criteria 并且这个条件是延迟加载的。所以find 更大的查询只命中数据库一次返回一个游标......所以不用担心性能.. . 另外,如果您希望查询根本不访问数据库...使用where 而不是find 这样您就可以获得Criteria ...而无需访问数据库。 ..您可以在需要时评估返回的标准(这将影响数据库)
    【解决方案2】:

    通过仔细研究似乎达到最佳点的文档找到了另一个答案——文本索引。

    db.collection.ensureIndex({"field1":"text","field2":"text"})
    db.records.runCommand("text",{search:"foo bar"})
    

    当我使用更多字符串和字段(以及大约 100,000 条记录)运行实际查询时,$or/$in 方法需要 620 毫秒,而文本索引需要 131 毫秒。一个缺点是它会返回不同类型的文档。幸运的是,实际文档是每个结果对象的参数。

    感谢那些花时间提出建议的人。

    【讨论】:

      【解决方案3】:

      我会通过添加它们的值来收集一个字段(即collected)中的所有相关字段

      "foo:field1", 
      "bar:field2", 
      "baz:field3",  
      "stuff:otherfield", 
      "bar:field1", 
      "baz:field2"
      ...
      

      进入那个领域。

      如果您搜索bar 存在于您可以使用的任何字段中:

      db.collection.find( { collected: { $regex: "^bar" } }, ... );
      

      您在问题中的示例如下所示:

      db.collection.find( collected: { { $all: [ "foo:field1", "foo:field2", "bar:field1", "bar:field2" ] } }, ... ); 
      

      【讨论】:

        猜你喜欢
        • 2022-01-25
        • 2021-05-16
        • 2013-03-21
        • 2018-07-13
        • 1970-01-01
        • 2012-02-06
        • 1970-01-01
        • 2017-11-06
        • 1970-01-01
        相关资源
        最近更新 更多