如何最好地处理 NEST 中的索引属性子字段?
How best to address index property sub-fields in NEST?
我正在尝试找出如何最好地让 NEST 驱动 Elastic 跨多字段属性的子字段进行搜索,如果可能的话,而不对查询中的字段名称进行硬编码。
一些解释...
我们有一个包含一些字段的 POCO 业务对象,因为我们知道这些字段可能是有些复杂的字母数字字符串,有时带有符号、标点符号和空格,用户可能会在没有修饰的情况下搜索这些字段,而且通常是相当局部的方式。
例如,一个项目代码可能像 "X123.45-10",但用户可能只能记住 "it ended '4510'"。为了找到这些,我们创建了一个索引,该索引具有具有多个字段的字符串属性,每个字段的分析方式不同,即 ngrammed 有和没有非字母字符:
client.CreateIndex(Elasticsearchindex, c => c
.Analysis(a => a.Analyzers(az1 => az1.Add("ngram_analyzer", ngramAnalyser)))
.Analysis(a => a.Analyzers(az1 => az1.Add("compressedNgramAnalyser", compressedNgramAnalyser)))
.AddMapping<ItemBo>(m => m.MapFromAttributes()
.Properties(props => props
.MultiField(s => s
.Name(p => p.ItemCode)
.Fields(pprops => pprops
.String(ps => ps.Name(p => p.ItemCode).Index(FieldIndexOption.Analyzed).Analyzer("default"))
.String(ps => ps.Name("ngram").Index(FieldIndexOption.Analyzed).IndexAnalyzer("ngram_analyzer"))
.String(ps => ps.Name("compressedNgram").Index(FieldIndexOption.Analyzed).IndexAnalyzer("compressedNgramAnalyser"))
)
)
)
)
);
这给了我们索引属性...
"itemCode": {
"type": "string",
"fields": {
"ngram": {
"type": "string",
"index_analyzer": "ngram_analyzer"
},
"compressedNgram": {
"type": "string",
"index_analyzer": "compressedNgramAnalyser"
}
}
},
最初我们假设如果我们在查询中包含该属性,子字段将被匹配...
sd.Query(q => q.QueryString(qs => qs
.Query(findText)
.OnFields(f => f.Description, f => f.ItemCode)));
...但这不会在子字段中查看,只是原始字段。
如果我们想要匹配子字段,我们似乎需要从类型化的 POCO 中脱钩并显式引用和通配索引字段...
sd.Query(q => q.QueryString(qs => qs
.Query(findText)
.OnFields(new[] {"description", "itemCode.*"}))
我是不是漏掉了什么技巧?有没有更好的方法来处理 NEST 查询中的索引属性子字段?
在主字段上搜索不会自动扩展到子字段;正如您已经发现的那样,您需要使用点符号来访问它们(itemCode.ngram
、itemCode.compressedNgram
等...)。
NEST 提供了一种聪明的方法来处理这个问题,同时仍然通过 Suffix()
扩展方法使用表达式:
.OnFields(x => x.ItemCode.Suffix("*"))
序列化后将转换为 itemCode.*
。
我正在尝试找出如何最好地让 NEST 驱动 Elastic 跨多字段属性的子字段进行搜索,如果可能的话,而不对查询中的字段名称进行硬编码。
一些解释...
我们有一个包含一些字段的 POCO 业务对象,因为我们知道这些字段可能是有些复杂的字母数字字符串,有时带有符号、标点符号和空格,用户可能会在没有修饰的情况下搜索这些字段,而且通常是相当局部的方式。
例如,一个项目代码可能像 "X123.45-10",但用户可能只能记住 "it ended '4510'"。为了找到这些,我们创建了一个索引,该索引具有具有多个字段的字符串属性,每个字段的分析方式不同,即 ngrammed 有和没有非字母字符:
client.CreateIndex(Elasticsearchindex, c => c
.Analysis(a => a.Analyzers(az1 => az1.Add("ngram_analyzer", ngramAnalyser)))
.Analysis(a => a.Analyzers(az1 => az1.Add("compressedNgramAnalyser", compressedNgramAnalyser)))
.AddMapping<ItemBo>(m => m.MapFromAttributes()
.Properties(props => props
.MultiField(s => s
.Name(p => p.ItemCode)
.Fields(pprops => pprops
.String(ps => ps.Name(p => p.ItemCode).Index(FieldIndexOption.Analyzed).Analyzer("default"))
.String(ps => ps.Name("ngram").Index(FieldIndexOption.Analyzed).IndexAnalyzer("ngram_analyzer"))
.String(ps => ps.Name("compressedNgram").Index(FieldIndexOption.Analyzed).IndexAnalyzer("compressedNgramAnalyser"))
)
)
)
)
);
这给了我们索引属性...
"itemCode": {
"type": "string",
"fields": {
"ngram": {
"type": "string",
"index_analyzer": "ngram_analyzer"
},
"compressedNgram": {
"type": "string",
"index_analyzer": "compressedNgramAnalyser"
}
}
},
最初我们假设如果我们在查询中包含该属性,子字段将被匹配...
sd.Query(q => q.QueryString(qs => qs
.Query(findText)
.OnFields(f => f.Description, f => f.ItemCode)));
...但这不会在子字段中查看,只是原始字段。
如果我们想要匹配子字段,我们似乎需要从类型化的 POCO 中脱钩并显式引用和通配索引字段...
sd.Query(q => q.QueryString(qs => qs
.Query(findText)
.OnFields(new[] {"description", "itemCode.*"}))
我是不是漏掉了什么技巧?有没有更好的方法来处理 NEST 查询中的索引属性子字段?
在主字段上搜索不会自动扩展到子字段;正如您已经发现的那样,您需要使用点符号来访问它们(itemCode.ngram
、itemCode.compressedNgram
等...)。
NEST 提供了一种聪明的方法来处理这个问题,同时仍然通过 Suffix()
扩展方法使用表达式:
.OnFields(x => x.ItemCode.Suffix("*"))
序列化后将转换为 itemCode.*
。