【问题标题】:Mongodb query combining $text search with $regex将 $text 搜索与 $regex 相结合的 Mongodb 查询
【发布时间】:2020-12-06 04:58:10
【问题描述】:

我的困境是 mongodb $text 搜索必须匹配一个确切的单词:例如如果尝试使用 'testing123' 匹配帖子,则搜索 'test'匹配,但使用 $regex 将匹配。现在,我也想使用索引,但我也想要部分匹配。

我的想法是我可以将它们与$or 运算符结合使用,但它不起作用。这可能吗? $or 中的每个查询单独工作,但是在组合它们时我没有得到匹配。

如果这不可能,我已经找到了一个很好的解决方案,here,但如果可能的话,我希望组合 $or 可以工作,但欢迎任何其他建议。

const posts = await Post.find({
  name: { $regex: 'foo', $options: 'i' },
  $or: [
    { $text: { $search: text, $caseSensitive: false } },
    { text: { $regex: text, $options: 'i' } },
  ],
});

【问题讨论】:

    标签: javascript mongodb mongoose nosql


    【解决方案1】:

    这样做的一种方法是将文本小写到另一个字段,然后在该字段上使用 $regex 搜索。


    您有想要不区分大小写地搜索任何子字符串的文本:

    MongoDB Enterprise ruby-driver-rs:PRIMARY> db.foo.insert({foo:'hello world TESTING123'})
    WriteResult({ "nInserted" : 1 })
    

    第 1 步:添加另一个以小写形式存储文本的字段。

    MongoDB Enterprise ruby-driver-rs:PRIMARY> db.foo.insert({foo:'hello world TESTING123',foo_lower:'hello world testing123'})
    

    第 2 步:添加索引。

    MongoDB Enterprise ruby-driver-rs:PRIMARY> db.foo.createIndex({foo_lower:1})
    {
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 2,
        "numIndexesAfter" : 3,
        "commitQuorum" : "votingMembers",
        "ok" : 1,
        "$clusterTime" : {
            "clusterTime" : Timestamp(1597711723, 7),
            "signature" : {
                "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                "keyId" : NumberLong(0)
            }
        },
        "operationTime" : Timestamp(1597711723, 7)
    }
    

    第 3 步:将查询小写为“testing123”

    第 4 步:使用 $regex。

    MongoDB Enterprise ruby-driver-rs:PRIMARY> db.foo.find({foo_lower:{$regex:'testing123'}})
    { "_id" : ObjectId("5f3b2498f885e53d90f30979"), "foo" : "hello world TESTING123", "foo_lower" : "hello world testing123" }
    MongoDB Enterprise ruby-driver-rs:PRIMARY> db.foo.find({foo_lower:{$regex:'testing123'}}).explain()
    {
        "queryPlanner" : {
            "plannerVersion" : 1,
            "namespace" : "test.foo",
            "indexFilterSet" : false,
            "parsedQuery" : {
                "foo_lower" : {
                    "$regex" : "testing123"
                }
            },
            "queryHash" : "0D14CC56",
            "planCacheKey" : "1974A2D4",
            "winningPlan" : {
                "stage" : "FETCH",
                "inputStage" : {
                    "stage" : "IXSCAN",
                    "filter" : {
                        "foo_lower" : {
                            "$regex" : "testing123"
                        }
                    },
                    "keyPattern" : {
                        "foo_lower" : 1
                    },
                    "indexName" : "foo_lower_1",
                    "isMultiKey" : false,
                    "multiKeyPaths" : {
                        "foo_lower" : [ ]
                    },
                    "isUnique" : false,
                    "isSparse" : false,
                    "isPartial" : false,
                    "indexVersion" : 2,
                    "direction" : "forward",
                    "indexBounds" : {
                        "foo_lower" : [
                            "[\"\", {})",
                            "[/testing123/, /testing123/]"
                        ]
                    }
                }
            },
            "rejectedPlans" : [ ]
        },
        "serverInfo" : {
            "host" : "serene",
            "port" : 14420,
            "version" : "4.4.0",
            "gitVersion" : "563487e100c4215e2dce98d0af2a6a5a2d67c5cf"
        },
        "ok" : 1,
        "$clusterTime" : {
            "clusterTime" : Timestamp(1597711761, 1),
            "signature" : {
                "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                "keyId" : NumberLong(0)
            }
        },
        "operationTime" : Timestamp(1597711761, 1)
    }
    

    【讨论】:

    • 你能给我举个小例子来说明你的意思吗?
    • 不区分大小写的正则表达式匹配不支持索引,因此您创建另一个字段,其中文本被小写,您可以以区分大小写的方式进行搜索。
    • 这将如何解决部分搜索的问题?
    • 部分搜索精确词是什么意思?
    • 如果我尝试匹配具有 testing123 的帖子并且我只搜索 test,则 $text $search 将不匹配,但使用 $regex 将匹配。这就是我想将两者结合起来的原因。
    猜你喜欢
    • 1970-01-01
    • 2017-06-09
    • 1970-01-01
    • 1970-01-01
    • 2020-07-15
    • 1970-01-01
    • 2016-05-13
    • 1970-01-01
    • 2023-03-10
    相关资源
    最近更新 更多