Reputation: 59
I'm trying to work out how best to get NEST to drive Elastic to search across sub-fields of a multifield property, if possible without hardcoding the field names in the query.
Some explanation...
We have a POCO business object with some fields in that we know can be somewhat complicated strings of alphanumeric, sometimes with symbols, punctuation and whitespace, that users are likely to search for without the decoration and often in a fairly partial way.
For example, an item code may be like "X123.45-10", but a user may be only able to remember "it ended '4510'". In order to find these we have created an index with a string property that has multiple fields, each analysed differently, i.e. ngrammed with and without the non-alpha characters:
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"))
)
)
)
)
);
which gives us the index property...
"itemCode": {
"type": "string",
"fields": {
"ngram": {
"type": "string",
"index_analyzer": "ngram_analyzer"
},
"compressedNgram": {
"type": "string",
"index_analyzer": "compressedNgramAnalyser"
}
}
},
Originally we had assumed that if we included the property in a query, the sub-fields would be matched...
sd.Query(q => q.QueryString(qs => qs
.Query(findText)
.OnFields(f => f.Description, f => f.ItemCode)));
...but that doesn't look in the sub-fields, just the original.
If we want to match the sub-fields, we seem to need to unhook from the typed POCO and refer to and wildcard the index fields explicitly...
sd.Query(q => q.QueryString(qs => qs
.Query(findText)
.OnFields(new[] {"description", "itemCode.*"}))
Am I missing a trick here? Is there some better way of addressing the index property sub-fields in a NEST query?
Upvotes: 0
Views: 370
Reputation: 3325
Searching on the main field won't automatically extend to sub-fields; you need to use dot notation to access them (itemCode.ngram
, itemCode.compressedNgram
etc...) as you've already discovered.
NEST offers a clever way to deal with this while still using expressions through the Suffix()
extension method:
.OnFields(x => x.ItemCode.Suffix("*"))
which will translate to itemCode.*
when serialized.
Upvotes: 1