I have items in my ElasticSearch as follows:
{
"superItems_1": {
"mappings": {
"properties": {
"aliasNames": {
"type": "keyword",
"normalizer": "lowercase_normalizer"
},
"typeCode": {
"type": "text"
},
"mainName": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}}
What I want is to do searches to this ElasticSearch in two ways.
First, just do fuzzysearch against aliasNames and mainNames and ignore the typeCode. Here's my current implementation in C#:
var withoutTypeIdentifier = await ESClient.SearchAsync<ElasticSearchEntity>(s => s
.Index(indexName)
.Query(q => q.Bool(b => b
.Should(
should => should.Match(m => m
.Field(f => f.MainName)
.Query(searchValue)
.Fuzziness(new Fuzziness("Auto"))
.PrefixLength(0)
.MaxExpansions(50)
),
should => should.Match(m => m
.Field(f => f.AliasNames)
.Query(searchValue)
.Fuzziness(new Fuzziness("Auto"))
.PrefixLength(0)
.MaxExpansions(50)
)
)
)));
This works nicely, but here's the issue:
THEN, I want to add the typeCodes, which I have as a List<string> typeCodes
, So if the SuperItems has an item with TypeCode: "OUTDATED", and user searches for {"OUTDATED","DELETED"}
it will match with the "OUTDATED". Every item has this TypeCode. Here's my attempt, but I can not figure out how to give the entire list:
var searchResponse = await ESClient.SearchAsync<ElasticSearchEntity>(s => s
.Index(indexName)
.Query(q => q.Bool(b => b
.Must(m => m
.Term(t => t
.Field(f => f.TypeCodes.Suffix("keyword"))
.Value(typeCodes) <--- How ???
)
)
.Should(
should => should.Match(m => m
.Field(f => f.FullName)
.Query(searchValue)
.Fuzziness(new Fuzziness("AUTO"))
.PrefixLength(0)
.MaxExpansions(50)
),
should => should.Match(m => m
.Field(f => f.AliasNames)
.Query(searchValue)
.Fuzziness(new Fuzziness("AUTO"))
.PrefixLength(0)
.MaxExpansions(50)
)
)
)));
Of course I asked from the AI, but that thing just keeps telling me to use this implementation, which does not work, and has ambiguous invocations, and it just can't fix it no matter what I ask.
var searchResponse = await ESClient.SearchAsync<ElasticSearchEntity>(s => s
.Index(indexName)
.Query(q =>
q.Bool(b => b
.Must(m => m.Terms(c => c <-- This gives an error: Ambiquous invocation
.Field("typeCodes.keyword")
.Terms(typeCodes)
))
.Should(
sh => sh.Match(d => d
.Field("fullName")
.Query(searchValue)
.Fuzziness("AUTO")
ETC...
I'm using the latest Elastic.Clients.Elasticsearch;
Any thoughts on how to implement this?
I have items in my ElasticSearch as follows:
{
"superItems_1": {
"mappings": {
"properties": {
"aliasNames": {
"type": "keyword",
"normalizer": "lowercase_normalizer"
},
"typeCode": {
"type": "text"
},
"mainName": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}}
What I want is to do searches to this ElasticSearch in two ways.
First, just do fuzzysearch against aliasNames and mainNames and ignore the typeCode. Here's my current implementation in C#:
var withoutTypeIdentifier = await ESClient.SearchAsync<ElasticSearchEntity>(s => s
.Index(indexName)
.Query(q => q.Bool(b => b
.Should(
should => should.Match(m => m
.Field(f => f.MainName)
.Query(searchValue)
.Fuzziness(new Fuzziness("Auto"))
.PrefixLength(0)
.MaxExpansions(50)
),
should => should.Match(m => m
.Field(f => f.AliasNames)
.Query(searchValue)
.Fuzziness(new Fuzziness("Auto"))
.PrefixLength(0)
.MaxExpansions(50)
)
)
)));
This works nicely, but here's the issue:
THEN, I want to add the typeCodes, which I have as a List<string> typeCodes
, So if the SuperItems has an item with TypeCode: "OUTDATED", and user searches for {"OUTDATED","DELETED"}
it will match with the "OUTDATED". Every item has this TypeCode. Here's my attempt, but I can not figure out how to give the entire list:
var searchResponse = await ESClient.SearchAsync<ElasticSearchEntity>(s => s
.Index(indexName)
.Query(q => q.Bool(b => b
.Must(m => m
.Term(t => t
.Field(f => f.TypeCodes.Suffix("keyword"))
.Value(typeCodes) <--- How ???
)
)
.Should(
should => should.Match(m => m
.Field(f => f.FullName)
.Query(searchValue)
.Fuzziness(new Fuzziness("AUTO"))
.PrefixLength(0)
.MaxExpansions(50)
),
should => should.Match(m => m
.Field(f => f.AliasNames)
.Query(searchValue)
.Fuzziness(new Fuzziness("AUTO"))
.PrefixLength(0)
.MaxExpansions(50)
)
)
)));
Of course I asked from the AI, but that thing just keeps telling me to use this implementation, which does not work, and has ambiguous invocations, and it just can't fix it no matter what I ask.
var searchResponse = await ESClient.SearchAsync<ElasticSearchEntity>(s => s
.Index(indexName)
.Query(q =>
q.Bool(b => b
.Must(m => m.Terms(c => c <-- This gives an error: Ambiquous invocation
.Field("typeCodes.keyword")
.Terms(typeCodes)
))
.Should(
sh => sh.Match(d => d
.Field("fullName")
.Query(searchValue)
.Fuzziness("AUTO")
ETC...
I'm using the latest Elastic.Clients.Elasticsearch;
Any thoughts on how to implement this?
The type of typeCode
is text
. Therefore your first way is to use the match
query. I demonstrate it in the terms of Elasticsearch queries, not c#.
Sample documents
POST /only_text_field/_bulk
{"create":{}}
{"typeCode":"OUTDATED"}
{"create":{}}
{"typeCode":"DELETED"}
{"create":{}}
{"typeCode":"ANOTHER"}
match
query with a list of values converted into a string
GET /only_text_field/_search?filter_path=hits.hits._source
{
"query": {
"match": {
"typeCode": "OUTDATED DELETED"
}
}
}
Response
{
"hits" : {
"hits" : [
{
"_source" : {
"typeCode" : "OUTDATED"
}
},
{
"_source" : {
"typeCode" : "DELETED"
}
}
]
}
}
Your second way is to update mapping with converting typeCode
into a multi-field with the keyword
representation. Then you should use the terms
query
GET /only_text_field/_search?filter_path=hits.hits._source
{
"query": {
"terms": {
"typeCode.keyword": ["OUTDATED", "DELETED"]
}
}
}
Response
{
"hits" : {
"hits" : [
{
"_source" : {
"typeCode" : "OUTDATED"
}
},
{
"_source" : {
"typeCode" : "DELETED"
}
}
]
}
}