一尘不染

NEST查询以精确匹配文本

elasticsearch

我正在尝试编写一个NEST查询,该查询应基于完全匹​​配的字符串返回结果。我已经在网络上进行了研究,并且对使用术语,匹配,匹配短语有一些建议。我已经尝试了所有这些方法,但是搜索返回的结果中包含搜索字符串的一部分。例如,在我的数据库中,我有以下几行电子邮件地址:

ter@gmail.com

ter@hotmail.com

terrance@hotmail.com

无论我是否使用:

client.Search<Emails>(s => s.From(0)
                        .Size(MaximumSearchResultsSize)
                        .Query(q => q.Term( p=> p.OnField(fielname).Value(fieldValue))))

要么

  client.Search<Emails>(s => s.From(0).
                              Size(MaximumPaymentSearchResults).
                              Query(q=>q.Match(p=>p.OnField(fieldName).Query(fieldValue))));

我的搜索结果总是返回包含“部分搜索”字符串的行。

因此,如果我将搜索字符串提供为“ ter”,则仍会得到所有3行。ter@gmail.com

ter@hotmail.com

terrance@hotmail.com

如果搜索字符串为“ ter”,我希望看不到返回的行。如果搜索字符串为“ ter@hotmail.com”,那么我只希望看到“
ter@hotmail.com”。

不知道我在做什么错。


阅读 702

收藏
2020-06-22

共1个答案

一尘不染

根据问题中提供的信息,听起来好像包含电子邮件地址的字段已用 Standard
Analyzer
索引,如果未指定其他分析器或未将字段标记为,则默认的分析器应用于字符串字段not_analyzed

通过使用Elasticsearch 的 Analyze
API
,可以看到标准分析器对给定字符串输入的影响:

curl -XPOST "http://localhost:9200/_analyze?analyzer=standard&text=ter%40gmail.com

文本输入需要进行url编码,如此处用@符号所示。运行此查询的结果是

{
   "tokens": [
      {
         "token": "ter",
         "start_offset": 0,
         "end_offset": 3,
         "type": "<ALPHANUM>",
         "position": 1
      },
      {
         "token": "gmail.com",
         "start_offset": 4,
         "end_offset": 13,
         "type": "<ALPHANUM>",
         "position": 2
      }
   ]
}

我们可以看到标准分析器为输入ter和生成了两个标记gmail.com,这将存储在字段的倒排索引中。

现在,运行 匹配
查询
将导致对
匹配

查询
的输入进行分析,默认情况下,使用与在其中应用匹配查询的字段的映射定义中找到的分析器相同的分析器。

然后,默认情况下,将从此匹配查询分析得到的标记组合到 布尔值或 查询中,这样,包含该字段的反向索引中包含任何标记的任何文档都是匹配项。举个例子

text ter@gmail.com,这意味着与该字段匹配ter或匹配的任何文档gmail.com都会被点击

// Indexing
input: ter@gmail.com -> standard analyzer -> ter,gmail.com in inverted index

// Querying
input: ter@gmail.com -> match query -> docs with ter or gmail.com are a hit!

显然,对于完全匹配,这根本不是我们想要的!

运行 术语
查询
将导致
分析术语查询的输入,即,它是对与术语输入完全匹配的查询,但是在索引时间已分析的字段上运行此查询可能会成为问题;由于已对该字段的值进行了分析,但尚未对术语查询进行输入,因此您将获得返回的结果,该结果与在索引时间发生的分析结果完全匹配术语输入。例如

// Indexing
input: ter@gmail.com -> standard analyzer -> ter,gmail.com in inverted index

// Querying
input: ter@gmail.com -> term query -> No exact matches for ter@gmail.com

input: ter -> term query -> docs with ter in inverted index are a hit!

这也不是我们想要的!

我们可能要对该字段进行的操作是将其设置not_analyzed为映射定义中

putMappingDescriptor
    .MapFromAttributes()
    .Properties(p => p
        .String(s => s.Name(n => n.FieldName).Index(FieldIndexOption.NotAnalyzed)
    );

有了此功能后,我们可以使用
过滤

查询
通过
术语

过滤器
搜索 完全匹配
****

****

// change dynamic to your type
var docs = client.Search<dynamic>(b => b
    .Query(q => q
        .Filtered(fq => fq
            .Filter(f => f
                .Term("fieldName", "ter@gmail.com")
            )
        )
    )
);

这将产生以下查询DSL

{
  "query": {
    "filtered": {
      "filter": {
        "term": {
          "fieldName": "ter@gmail.com"
        }
      }
    }
  }
}
2020-06-22