【问题标题】:Elasticsearch query with NEST don't work使用 NEST 的 Elasticsearch 查询不起作用
【发布时间】:2017-03-02 09:36:43
【问题描述】:

我将 Microsoft SQL Server Management Studio 和 ElasticSearch 2.3.4 与 ElasticSearch-jdbc-2.3.4.1 一起使用,并将 ES 与我的 mssql 服务器链接。一切正常,但是当我在 MVC 程序上使用 NEST 进行查询时,结果为空。当我在search 属性中放入一个空字符串时,我得到了元素,但是当我尝试用一​​些过滤器填充它时,我得到一个空结果。有人可以帮帮我吗?提前致谢。

C#:

const string ESServer = "http://localhost:9200";
ConnectionSettings settings = new ConnectionSettings(new Uri(ESServer));
settings.DefaultIndex("tiky");
settings.MapDefaultTypeNames(map => map.Add(typeof(DAL.Faq), "faq"));
ElasticClient client = new ElasticClient(settings);

var response = client.Search<DAL.Faq>(s => s.Query(q => q.Term(x => x.Question, search)));

var result = response.Documents.ToList();

DAL:

邮递员:

PS:我关注this guide创建它

编辑:

索引映射:

【问题讨论】:

  • 可以分享索引映射吗? http://localhost:9200/tiky/_mapping
  • @Rob 当然,我已经更新了问题
  • Question 字段已分析,terms querynot_analyzed 字段一起使用。你可以阅读更多关于here的信息。
  • 哦,是的,我明白了。那么,如果我想获取包含该值的元素,我该怎么办?有什么办法不分析字符串?
  • 我不知道你搜索case,但我想你可以从match query开始。

标签: c# sql-server asp.net-mvc elasticsearch nest


【解决方案1】:

我可以看到一些可能对这里有所帮助的事情:

  1. 默认情况下,NEST Camel 在将 POCO 属性名称序列化为请求中查询 JSON 的一部分时会区分它们,因此x =&gt; x.Question 将序列化为"question"。然而,查看您的映射,Elasticsearch 中的字段名称是 Pascal 大小写的,因此客户端所做的与 Elasticsearch 中的不匹配。

您可以通过在 ConnectionSettings 上使用 .DefaultFieldNameInferrer(Func&lt;string, string&gt;) 来更改 NEST 序列化 POCO 属性名称的方式

const string ESServer = "http://localhost:9200";
ConnectionSettings settings = new ConnectionSettings(new Uri(ESServer))
    .DefaultIndex("tiky");
    .MapDefaultTypeNames(map => map.Add(typeof(DAL.Faq), "faq"))
    // pass POCO property names through verbatim
    .DefaultFieldNameInferrer(s => s);

ElasticClient client = new ElasticClient(settings);
  1. 正如 Rob 在 cmets 中提到的,a term query 不分析查询输入。当针对在索引时分析的字段执行术语查询时,为了获得匹配,您传递给术语查询的查询文本需要考虑在索引时应用的​​分析。例如,

    • Questionthe Standard Analyzer 进行分析
    • "What's the Question?"Question 值将被分析并索引为标记 "what's""the""question"
    • 术语查询需要有"what's""the""question" 的查询输入才能匹配

匹配查询与术语查询不同,它会分析查询输入,因此搜索分析的输出将用于查找匹配项。结合 1. 中突出显示的 Pascal 大小写,您现在应该可以返回文档。

您还可以在 Elasticsearch 中两全其美,即在索引时分析输入以获取全文搜索功能,以及在不分析的情况下索引输入以获得精确匹配。这是使用multi-fields 完成的,这里是创建一个映射的示例,该映射将Question 属性索引为已分析和未分析

public class Faq
{
    public string Question { get; set; }
}

var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var defaultIndex = "default-index";
var connectionSettings = new ConnectionSettings(pool)
        .DefaultIndex(defaultIndex)
        .DefaultFieldNameInferrer(s => s);

var client = new ElasticClient(connectionSettings);

if (client.IndexExists(defaultIndex).Exists)
    client.DeleteIndex(defaultIndex);

client.CreateIndex(defaultIndex, c => c
    .Mappings(m => m
        .Map<Faq>(mm => mm
            // let NEST infer mapping from the POCO
            .AutoMap()
            // override any inferred mappings explicitly
            .Properties(p => p
                .String(s => s
                    .Name(n => n.Question)
                    .Fields(f => f
                        .String(ss => ss
                            .Name("raw")
                            .NotAnalyzed()
                        )
                    )
                )
            )
        )
    )
);   

这个映射看起来像

{
  "mappings": {
    "faq": {
      "properties": {
        "Question": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        }
      }
    }
  }
}

"Question" 字段下的"raw" 子字段将索引Question 属性的值,无需任何分析,即逐字记录。现在可以在术语查询中使用此子字段来查找完全匹配项

client.Search<Faq>(s => s
    .Query(q => q
        .Term(f => f.Question.Suffix("raw"), "What's the Question?")
    )
);

查找上一个示例的匹配项。

【讨论】:

  • 感谢您的提示!这实际上是我所需要的,并且描述得很好,谢谢!
猜你喜欢
  • 2022-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-05
  • 2023-03-31
  • 2013-07-06
相关资源
最近更新 更多