2015-08-25 33 views
3

我想写一个NEST查询,应该返回基于完全字符串匹配的结果。我在网上进行了研究,并提出了有关使用术语,匹配,匹配的建议。我尝试了所有这些,但是我的搜索返回的结果包含部分搜索字符串。 例如,在我的数据库,我有以下电子邮件地址的行:确切的文本匹配的NEST查询

[email protected]

[email protected]

[email protected]

不论我用途:

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))));            

我的搜索结果总是返回包含“部分搜索”字符串的行。所以,如果我提供的搜索字符串为“三”,我仍然得到所有3行。 [email protected]

[email protected]

[email protected]

我希望看到任何行返回如果搜索字符串是“之三”。如果搜索字符串是“ [email protected]“然后我想只看到”[email protected]“。

不知道我在做什么错。

+0

你可以分享你的电子邮件字段的映射吗? – Val

+0

感谢Val的回应。问题在于你和Russ已经指出的映射。 – CSC

回答

2

根据你在问题中提供的信息,这听起来像一个包含电子邮件地址,如果没有指定其他分析仪或被索引与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 
     } 
    ] 
} 

我们可以看到,标准分析器产生两个令牌输入,tergmail.com,这就是将存储在该领域的倒排索引。

现在,运行Match query将导致对匹配查询的输入进行分析,默认情况下,使用与应用匹配查询的字段的映射定义中发现的分析器相同的分析器。

从匹配查询分析得到的标记然后默认合并到布尔值或查询中,以便包含该字段的反向索引中的任何一个标记的任何文档都是匹配项。对于例如

文本[email protected],这将意味着有一个匹配tergmail.com的字段的任何文件将是一个打击

// Indexing 
input: [email protected] -> standard analyzer -> ter,gmail.com in inverted index 

// Querying 
input: [email protected] -> match query -> docs with ter or gmail.com are a hit! 

显然,精确匹配,这不是我们打算根本!

运行Term query将导致输入项查询进行分析,也就是说,它的精确匹配的词输入一个查询,但对已在索引时间进行了分析现场运行,这可能可能是一个问题;由于该字段的值已进行了分析,但是对查询词的输入尚未进行,因此您将获得与输入词作为索引时发生的分析结果完全匹配的结果。例如

// Indexing 
input: [email protected] -> standard analyzer -> ter,gmail.com in inverted index 

// Querying 
input: [email protected] -> term query -> No exact matches for [email protected] 

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) 
    ); 

有了这个地方是什么,我们可以搜索精确与使用Filtered query

一个Term filter匹配
// change dynamic to your type 
var docs = client.Search<dynamic>(b => b 
    .Query(q => q 
     .Filtered(fq => fq 
      .Filter(f => f 
       .Term("fieldName", "[email protected]") 
      ) 
     ) 
    ) 
); 

将产生以下查询DSL

{ 
    "query": { 
    "filtered": { 
     "filter": { 
     "term": { 
      "fieldName": "[email protected]" 
     } 
     } 
    } 
    } 
} 
+0

非常感谢。这解决了这个问题。 – CSC

+0

没有probs,乐意帮忙! –

+0

属性上的属性为我排序,但你让我回答(PS:'[ElasticProperty(Index = FieldIndexOption.NotAnalyzed)]') – DavidG