mongoDB前缀通配符:fulltext-search($text)使用搜索字符串查找部分

bz4sfanl  于 2022-11-03  发布在  Go
关注(0)|答案(7)|浏览(292)

我有一个带有$text-Index的mongodb和如下元素:

{
   foo: "my super cool item"
}
{
   foo: "your not so cool item"
}

如果我用

mycoll.find({ $text: { $search: "super"} })

我得到了第一项(正确)。
但我也想用“uper”搜索得到第一个项目-但如果我尝试:

mycoll.find({ $text: { $search: "uper"} })

我没有得到任何结果。
我的问题:是否有一种方法可以使用$text,使其查找结果包含搜索字符串的一部分?(例如,mysql中的'%uper%'

收件人:我不要求只搜索正则表达式-我要求在$文本搜索中搜索正则表达式!

ffx8fchx

ffx8fchx1#

使用$text运算符无法完成此操作。
文本索引是使用字符串值或字符串数组中包含的术语创建的,并且搜索是基于这些索引的。
您只能对短语上的术语进行分组,但不能将其作为其中的一部分。
读取$text operator referencetext indexes description

67up9zun

67up9zun2#

最好的解决方案是同时使用文本索引和正则表达式。
该索引将提供出色的速度性能,但匹配的文档数量不如正则表达式。
如果索引没有返回足够的结果,正则表达式将允许回退。

db.mycoll.createIndex({ foo: 'text' });
db.mycoll.createIndex({ foo: 1 });
db.mycoll.find({
  $or: [
    { $text: { $search: 'uper' } },
    { foo: { $regex: 'uper' } }
  ]
});

为了获得更好的性能(但结果略有不同),请在正则表达式中使用^

db.mycoll.find({
  $or: [
    { $text: { $search: 'uper' } },
    { foo: { $regex: '^uper' } }
  ]
});
pbossiut

pbossiut3#

在第二个示例中,您尝试在集合mycoll中的字段foo上进行前缀通配符搜索。这不是文本搜索功能的设计目的,也不可能使用$text操作符来实现。此行为不包括在索引字段中的任何给定标记上进行通配符前缀搜索。但是,您也可以按照其他人的建议执行正则表达式搜索。以下是我的演练:

>db.mycoll.find()
{ "_id" : ObjectId("53add9364dfbffa0471c6e8e"), "foo" : "my super cool item" }
{ "_id" : ObjectId("53add9674dfbffa0471c6e8f"), "foo" : "your not so cool item" }
> db.mycoll.find({ $text: { $search: "super"} })
{ "_id" : ObjectId("53add9364dfbffa0471c6e8e"), "foo" : "my super cool item" }
> db.mycoll.count({ $text: { $search: "uper"} })
0

$text运算符支持搜索单个单词、搜索一个或多个单词或搜索短语。不支持您希望的搜索类型
正则表达式解决方案:

> db.mycoll.find({foo:/uper/})
{ "_id" : ObjectId("53add9364dfbffa0471c6e8e"), "foo" : "my super cool item" }
>

最后一个问题的答案:要在mongoDB中执行mysql风格%super%,您很可能必须执行以下操作:

db.mycoll.find( { foo : /.*super.*/ } );
jfgube3f

jfgube3f4#

它应该可以与/uper/一起使用。
有关详细信息,请参阅http://docs.mongodb.org/manual/reference/operator/query/regex/

编辑:

根据备注中的要求:
解决方案并不一定是要给予楼主 * 要求 * 的东西,而是他解决问题所需要的东西。
由于$regex搜索不支持文本索引,因此对索引字段进行简单的正则表达式搜索应该会给予预期的 * 结果 *,尽管没有使用请求的 * 方法 *。
实际上,这很容易做到:

db.collection.insert( {foo: "my super cool item"} )
db.collection.insert( {foo: "your not so cool item"})
db.collection.ensureIndex({ foo: 1 })
db.collection.find({'foo': /uper/})

给出了我们预期的结果:

{ "_id" : ObjectId("557f3ba4c1664dadf9fcfe47"), "foo" : "my super cool item" }

一个附加的解释向我们展示了索引的有效使用:

{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "test.collection",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "foo" : /uper/
        },
        "winningPlan" : {
            "stage" : "FETCH",
            "inputStage" : {
                "stage" : "IXSCAN",
                "filter" : {
                    "foo" : /uper/
                },
                "keyPattern" : {
                    "foo" : 1
                },
                "indexName" : "foo_1",
                "isMultiKey" : false,
                "direction" : "forward",
                "indexBounds" : {
                    "foo" : [
                        "[\"\", {})",
                        "[/uper/, /uper/]"
                    ]
                }
            }
        },
        "rejectedPlans" : [ ]
    },
    "serverInfo" : {
        // skipped
    },
    "ok" : 1
}

长话短说:不,您不能重用$text索引,但是可以高效地执行查询。就像在Implement auto-complete feature using MongoDB search中编写的那样,使用map/reduce方法可能会更高效,从索引中消除冗余和不必要的停止词,代价是不再是真实的的。

n3h0vuf2

n3h0vuf25#

正如francadaval所说,文本索引是按术语搜索的,但如果你把regextext-index结合起来,你应该很好。

mycoll.find({$or: [ 
  { 
    $text: {
      $search: "super"
    }
  },
  {
    'column-name': {
      $regex: 'uper',
      $options: 'i'
  }
]})

此外,请确保对列应用了普通索引,而不是文本索引。

k2arahey

k2arahey6#

如果你使用正则表达式,你可以搜索“super cool”,但不能搜索“super item”,用$text和$regex来实现request do an或request。
请确保对文本索引和普通索引都进行索引。

mtb9vblg

mtb9vblg7#

你本可以做到的是-

db.mycoll.find( {foo: { $regex :  /uper/i  } })

这里'i'是一个选项,表示不区分大小写的搜索

相关问题