【问题标题】:ElasticSearch NEST Indexing and Searching multiple fieldsElasticSearch NEST 索引和搜索多个字段
【发布时间】:2017-08-24 22:30:52
【问题描述】:

我正在学习 ElasticSearch 并使用 NEST。我有一个对象,想索引多个字段,然后搜索这些字段的组合。当我搜索时,我得到的结果与我的搜索字符串不匹配。下面是索引数据的代码。

client.CreateIndex(CurrentIndexName, i => i
    .Settings(s => s
      .NumberOfShards(2)
      .NumberOfReplicas(0)
      .Analysis(analysis => analysis
        .Analyzers(analyzer => analyzer
          .Custom("substring_analyzer", analyzerDescripter => analyzerDescripter
            .Tokenizer("tokenizer")
            .Filters("lowercase")
          )
        )
        .Tokenizers(tk => tk
          .EdgeNGram("tokenizer", tokenizer => tokenizer
            .MaxGram(10)
            .MinGram(2)
            .TokenChars(new List<TokenChar> { TokenChar.Letter, TokenChar.Digit })
          )
        )
      )
    )
    .Mappings(m => m
      .Map<CostCenter>(map => map
        .AutoMap()
        .Properties(ps => ps
          .Text(s => s
            .Name(n => n.CC_Acct_1)
            .Analyzer("substring_analyzer")
          )
          .Text(s => s
            .Name(n => n.CC_Acct_2)
            .Analyzer("substring_analyzer")
          )
          .Text(s => s
            .Name(n => n.CC_Acct_3)
            .Analyzer("substring_analyzer")
          )
        )
      )
    )
  );

这是我的搜索代码。

      var searchResult = client.Search<CostCenter>(s => s
    .Size(1000)
    .Query(q => q
      .Match(m => m
        .Field(f => f.CC_Acct_1)
        .Query("0061")
      ) &&
      q.Match(m => m
        .Field(f => f.CC_Acct_2)
        .Query("9061")
      )
    )
  );

这样,我得到的结果与任一字符串都不匹配(即 CC_Acct_1 = "0056" 和 CC_Acct_2 = "9056")。如果我删除第二个匹配语句,一切似乎都有效。有可能做我想要完成的事情吗?

更新:以下是我正在编制索引的数据示例。

[{
   "Cost_Center": "0056-5711-05910000",
   "CC_Acct_1": "0056",
   "CC_Acct_2": "5711",
   "CC_Acct_3": "5910000",
   },
 {
   "Cost_Center": "0061-9061-05910000",
   "CC_Acct_1": "0061",
   "CC_Acct_2": "9061",
   "CC_Acct_3": "6790000",

 },
 {
   "Cost_Center": "0061-9061-05910000",
   "CC_Acct_1": "0061",
   "CC_Acct_2": "9061",
   "CC_Acct_3": "5910000",
 },
 {
   "Cost_Center": "0056-5711-05910000",
   "CC_Acct_1": "0056",
   "CC_Acct_2": "5711",
   "CC_Acct_3": "6790000",
   },
 {
   "Cost_Center": "0061-5711-05910000",
   "CC_Acct_1": "0061",
   "CC_Acct_2": "5711",
   "CC_Acct_3": "6790000",     
 },
 {
   "Cost_Center": "0056-9061-05910000",
   "CC_Acct_1": "0056",
   "CC_Acct_2": "9061",
   "CC_Acct_3": "5910000",
 },
 {
   "Cost_Center": "0056-9061-05910000",
   "CC_Acct_1": "0056",
   "CC_Acct_2": "9061",
   "CC_Acct_3": "5910000",
   },
 {
   "Cost_Center": "0056-5711-05910000",
   "CC_Acct_1": "0056",
   "CC_Acct_2": "5711",
   "CC_Acct_3": "5910000",
},
 {
   "Cost_Center": "0056-5711-05910000",
   "CC_Acct_1": "0056",
   "CC_Acct_2": "5711",
   "CC_Acct_3": "5910000",
   },
 {
   "Cost_Center": "0056-5711-05910000",
   "CC_Acct_1": "0056",
   "CC_Acct_2": "5711",
   "CC_Acct_3": "5910000",
 }
 ]

我做了进一步的研究,看起来匹配的项目在我的返回集的顶部(即更高的分数)。我希望返回的结果只有完全匹配的结果。例如,只有 CC_Acct_1 为“0061”且 CC_Acct_2 为“9061”的项目,或者如果我的第二个搜索字段项目中有“90”,其中 CC_Acct_2 包含“90”。在这种情况下,CC_Acct_2 为“9061”或“1090”的两个项目都将包括在内。

【问题讨论】:

  • 有可能。您能否更新您的问题以索引一些数据,并包含您期望为给定查询返回的内容?
  • 我正在尝试预先输入,以便在用户开始输入时显示可能的值。
  • 如需提前输入,请查看完成提示:elastic.co/guide/en/elasticsearch/reference/current/…。根据您希望提供类型提前搜索的方式,这可能适合您的需要。如果您需要执行更复杂的分析,那么它可能不合适,但从您提供的信息来看,它看起来可能很合适

标签: elasticsearch nest


【解决方案1】:

我已经取得了一些进展,但不确定这是最好的方法。首先,我将查询更改为以下内容。

var searchResult = client.Search<CostCenter>(s => s
    .Size(1000)
    .Index("test")
    .Query(q => q)
      .MatchPhrase(m => m
        .Field(f => f.CC_Acct_1)
        .Query("0056")
      ) &&
      q.MatchPhrase(m => m
        .Field(f => f.CC_Acct_2)
        .Query("9056")
      ) 
    )
  );

这返回了所需的结果,但是当我为第三个字段添加查询时,没有返回任何结果。

 var searchResult = client.Search<CostCenter>(s => s
    .Size(1000)
    .Index("test")
    .Query(q => q
      .MatchPhrase(m => m
        .Field(f => f.CC_Acct_1)
        .Query("0056")
      ) &&
      q.MatchPhrase(m => m
        .Field(f => f.CC_Acct_2)
        .Query("9056")
      ) &&
      q.MatchPhrase(m => m
        .Field(f => f.CC_Acct_3)
        .Query("679")
      )
    )
  );

然后我切换到以下并收到了想要的结果。

var searchResult = client.Search<CostCenter>(s => s
    .Size(1000)
    .Index("test")
    .Query(q => q
      .Bool(b => b
        .Must(bs => bs.Term(p => p.CC_Acct_1, "0056"),
          bs => bs.Term(p => p.CC_Acct_2, "9056"),
          bs => bs.Term(p => p.CC_Acct_3, "679")
        )          
      )
    )
  );

我可以删除任何 lambda 函数并仅获取与我要查找的内容匹配的项目。让我知道是否有更好更有效的方法来实现这一点。

【讨论】:

  • 鉴于示例数据,我看不出这里的第二个和第三个查询将如何返回匹配项 - 示例集合中没有包含 "679" 作为CC_Acct_3 一部分的项目,其中是满足查询的要求。
  • 很抱歉。上面包含的数据是数据集的部分样本。我最初在上面发布的是我拥有的实际代码,我没有检查最后一个术语是否匹配。我会更新它以获得匹配的数据。
猜你喜欢
  • 2021-08-12
  • 2013-08-13
  • 2015-09-12
  • 2018-01-12
  • 1970-01-01
  • 2018-05-29
  • 2018-12-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多