检查字段是否为MongoDB上字符串或文本搜索的子字符串

检查字段是否为MongoDB上字符串或文本搜索的子字符串,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,需要检查字段是否是给定输入字符串的子字符串,不敏感模式 样本单据: { "_id" : ObjectId("5e6ffe413f71835ae3aa4b60"), "f" : "Paul", "id" : 11811, "l" : "Green", "r" : 64 } db.collection.aggregate([ /** Add a field which will be true if any of the field 'f' or '

需要检查字段是否是给定输入字符串的子字符串,不敏感模式

样本单据:

{
    "_id" : ObjectId("5e6ffe413f71835ae3aa4b60"),
    "f" : "Paul",
    "id" : 11811,
    "l" : "Green",
    "r" : 64
  }
db.collection.aggregate([
  /** Add a field which will be true if any of the field 'f' or 'l' is a sub-string of input (Case-insensitive) */
  {
    $addFields: {
      result: {
        $or: [
          { $regexMatch: { input: "Paul Green", regex: "$f", options: "i" } }, /** Usually input is field & regex is actual input value, we tricked it for our requirement */
          { $regexMatch: { input: "Paul Green", regex: "$l", options: "i" } }
        ]
      }
    }
  },
  /** Filter for all docs where result field is true (Which leave docs where 'f' or 'l' is sub-string) */
  { $match: { result: true } },
  /** Remove added field result */
  { $project: { result: 0 } }
]);
如果字符串为Paul Green我想获取此项,因此我尝试执行以下查询:

db.getCollection('players').find({$or: [{'f': {'$regex': 'Paul Green', '$options': 'i'}},{'l': {'$regex': 'Paul Green', '$options': 'i'}}]})
这没有结果。 我还希望像pele这样的搜索能够给我pelè


我怎样才能做到这一点呢?

更新的答案:

据我所知,您希望实现搜索功能,然后您可以在MongoDB中研究专门为文本搜索实现的功能,根据我实现文本搜索的经验,如模糊/部分/全文/变音符号/不区分大小写文本搜索非常有帮助

因此,我的建议是,由于您正在搜索两个字段
f
l
-我建议将两个字段合并为一个字段
fl
&在其上创建一个文本索引,这样您的查询将针对一个搜索更有效的字段,请检查以下建议:

步骤1:如果您尚未创建合并字段,您现在可以通过MongoDB v
>=4.2
上的此查询进行合并(在较低版本中,您需要找到一种方法来执行
读取Coll&更新字段
使用聚合+$out
):

步骤2:
fl
字段上创建文本索引:

db.collection.createIndex( { fl: "text" } )
步骤3:您可以执行如下搜索,一个可选的投影
{fl:0}
,以删除响应中的
fl
字段

db.collection.find( { $text: { $search: "Paul Green" } }, {fl :0} )
注意:现在您可以获得
f
l
保罗、格林、保罗、格林、格雷恩、保罗、保罗、保罗、格雷恩、保罗、格雷厄姆、格雷厄姆、格雷厄姆或格雷厄姆的所有文档,因此大部分文档都可以得到整理。如果您不研究文本搜索,您仍然会研究下面的方法


实际答案:

{
    "_id" : ObjectId("5e6ffe413f71835ae3aa4b60"),
    "f" : "Paul",
    "id" : 11811,
    "l" : "Green",
    "r" : 64
  }
db.collection.aggregate([
  /** Add a field which will be true if any of the field 'f' or 'l' is a sub-string of input (Case-insensitive) */
  {
    $addFields: {
      result: {
        $or: [
          { $regexMatch: { input: "Paul Green", regex: "$f", options: "i" } }, /** Usually input is field & regex is actual input value, we tricked it for our requirement */
          { $regexMatch: { input: "Paul Green", regex: "$l", options: "i" } }
        ]
      }
    }
  },
  /** Filter for all docs where result field is true (Which leave docs where 'f' or 'l' is sub-string) */
  { $match: { result: true } },
  /** Remove added field result */
  { $project: { result: 0 } }
]);
通常,当您想要检查字符串字段中存在的输入值时,您会使用正则表达式来获取过滤后的文档

但是,当您想传入一个字符串
“Paul Green”
&检查字段是否是pass'd输入的子字符串时,普通正则表达式对您没有帮助。但如果您使用的是MongoDB版本
4.2
,您可以做以下几件事:

查询1:

{
    "_id" : ObjectId("5e6ffe413f71835ae3aa4b60"),
    "f" : "Paul",
    "id" : 11811,
    "l" : "Green",
    "r" : 64
  }
db.collection.aggregate([
  /** Add a field which will be true if any of the field 'f' or 'l' is a sub-string of input (Case-insensitive) */
  {
    $addFields: {
      result: {
        $or: [
          { $regexMatch: { input: "Paul Green", regex: "$f", options: "i" } }, /** Usually input is field & regex is actual input value, we tricked it for our requirement */
          { $regexMatch: { input: "Paul Green", regex: "$l", options: "i" } }
        ]
      }
    }
  },
  /** Filter for all docs where result field is true (Which leave docs where 'f' or 'l' is sub-string) */
  { $match: { result: true } },
  /** Remove added field result */
  { $project: { result: 0 } }
]);
测试:

注意:即使发送输入字符串,如
'PaulGreen'
,上述查询也会起作用,但缺点是它不会像您希望的那样为您提供结果:像pele这样的搜索会给我pelè,因为如果您想要获取此类数据,然后您需要使用排序规则,如果我们使用。因此,根据您的数据,您可以执行以下操作:

查询2:

{
    "_id" : ObjectId("5e6ffe413f71835ae3aa4b60"),
    "f" : "Paul",
    "id" : 11811,
    "l" : "Green",
    "r" : 64
  }
db.collection.aggregate([
  /** Add a field which will be true if any of the field 'f' or 'l' is a sub-string of input (Case-insensitive) */
  {
    $addFields: {
      result: {
        $or: [
          { $regexMatch: { input: "Paul Green", regex: "$f", options: "i" } }, /** Usually input is field & regex is actual input value, we tricked it for our requirement */
          { $regexMatch: { input: "Paul Green", regex: "$l", options: "i" } }
        ]
      }
    }
  },
  /** Filter for all docs where result field is true (Which leave docs where 'f' or 'l' is sub-string) */
  { $match: { result: true } },
  /** Remove added field result */
  { $project: { result: 0 } }
]);
基于空格分割字符串['Paul','Green']&传入查询:

db.collection.aggregate(
  /** Filter docs if any of the word exists in any of the fields 'f' or 'l' */
  [
    {
      $match: {
        $or: [
          { f: { $in: ["Paul", "Green"] } },
          { l: { $in: ["Paul", "Green"] } }
        ]
      }
    }
  ],
  { collation: { locale: "fr", strength: 1 } } // Applied collation ignores case & diacritics
);

注意:上述查询可能主要用于MongoDB版本>
3.4
,但如果您想搜索类似于
'PaulGreen'
的内容,则无法使用,出于某些原因,此查询的排序规则在mongodb Played中不起作用-请在实际数据库中测试它。

您真的必须根据
f
&
l
搜索“Paul Green”吗?你不能把它分成两部分&搜索字段吗?因为你的查询会检查字符串中的pass'd是字段的子字符串,但不检查字段是值中pass'd的子字符串。我必须按原样搜索。在这种情况下,有一种方法可以获取文档,但我们不能对其进行排序::
pele将给我pelè
无法完成..给我部分建议和Gre(缩写)@MD10:我不知道,你想把
Pau
Gre
作为输入传递(或者)相同的输入
Paul Green
你想得到字段值可以是
Pau
Gre
的文档吗?我的目标是实现这样的搜索@MD10:好的,在mongo中没有直接的方法来完成你想要的!!当您传入
Paul Green
时,您无法获取带有
pre
gre
的文档,除非您拆分输入字符串并作为输入传入。你最好的选择是Query1,或者因为你正在寻找
Pau
Gre
你可以将
Paul Green
拆分为
['Pau'、'Paul'、'Green'、'Gre']
从代码中使用
Query2
。好的,你可以拆分,请给我一些查询建议。