I am elasticsearch newbie.
I am trying to use elasticsearch to search some titles let's say books names.
From my client I am sending the user input string every 0.5 second to the server to give suggestions.
So it could be partial words and maybe typos.
What would be the best query/way to deal with that.
Any point on the right direction will be appreciated.
Thanks
// fuzzy query example but it is not answering for multiple words
return await client.search({
index: indexName,
body: {
query: {
fuzzy: {
title: userInputSentence
}
},
},
});
You can achieve auto-complete by adding ngram/prefix tokenizers - this will make the partial text entered to match the docs with the full length text.
Few references:
How to suggest (autocomplete) next word in elastic search?
https://hackernoon.com/elasticsearch-building-autocomplete-functionality-494fcf81a7cf
update:----------
Another option is to use Elasticsearch completion suggester and Index-Time Search-as-You-Type
Related
I have an elastic index containing a dictionary in each document.
Docs:
{
"name" : "name1",
"paymentDict":
{
"card1": { "CardType": "Credit", "CardName": "Axis"},
"card2": { "CardType": "Debit", "CardName": "Axis"}
}
}
Dictionary Type: Dictionary<int,object>
I am expecting a good amount of write on this elastic index and want to test the performance aspect and didn't find anything useful in elastic docs explaining explicitly about the dictionary indexing. Need help in below query
How does indexing work for the dictionary?
Is this indexing will be the same as List<object>?
that would be an object in Elasticsearch - https://www.elastic.co/guide/en/elasticsearch/reference/7.14/object.html
you could also make this super simple and just have a document per card, that way you flatten things out
I'm confused on what index type I should apply for my field for prefix search, many show search_as_you_type but I think auto complete is not what I'm going for.
I have a UUID field:
id: 34y72ca1-3739-41ff-bbec-f6d17479384c
The following terms should return the doc above:
3
34
34y72ca1
34y72ca1-3739
34y72ca1-3739-41ff-bbec-f6d17479384c
Using 3739 should not return it as it doesn't start with 3739. Initially this is what I was going for but then the wildcard field is not supported by Amazon AWS, so I compromise for prefix search instead of partial search.
I tried search_as_you_type field but it doesn't return the result when I use the whole ID. Actually, my use case is when user click enter, the results will be shown, instead of real-live when they type, so if speed is compromised its OK, just that I hope for something that will be good for many rows of data.
Thanks
If you have not explicitly defined any index mapping, then you need to use id.keyword field instead of the id field for the prefix query to show the appropriate results. This uses the keyword analyzer instead of the standard analyzer
{
"query": {
"prefix": {
"id.keyword": {
"value": "34y72ca1"
}
}
}
}
Otherwise, you can modify your index mapping, by adding multi fields for id field
I have elastic search index with documents having a field "backend_name" like:- google, goolge_staging, google_stg1 etc.
I want only those documents that have "backend_name" = google
I am trying with the term query like this:
{ "query": { "term": { "backend_name": "google" } } }
But it returns me document having "backend_name" as goolge_staging, google_stg1 too. I want just document with "backend_name" = google.
One way to resolve it is to have goolge_staging, google_stg1 etc. in must not list but I want some better way. Suggestions?
It is provably because of the mapping you are using.
Take a look at the Elasticsearch documentation of term query
Try changing the mapping type to keyword so it matches only if it is an exact match.
I have an issue with elasticsearch and the way the data are indexed/retrieved. I don't understand what happens.
This is the mapping I use (sorry, it's yaml format) :
The idea is simple, in theory... I have a string analyzer with lowercase and asciifolding filters. I don't want to care about case or accents, and I would like to use this analyzer to index and search.
settings:
index:
analysis:
filter:
autocomplete_filter:
type: edgeNGram
side: front
min_gram: 1
max_gram: 20
analyzer:
autocomplete:
type: custom
tokenizer: standard
filter: [lowercase, asciifolding, autocomplete_filter]
string_analyzer:
type: custom
tokenizer: standard
filter: [lowercase, asciifolding]
types:
city:
mappings:
cityName:
type: string
analyzer: string_analyzer
search_analyzer: string_analyzer
location: {type: geo_point}
When I run this query :
{
"query": {
"prefix":{
"cityName":"per"
}
}
,
"size":20
}
I get some results like "Perpezat", "Pern", "Péreuil" which is the excepted result.
But if I run the following query :
{
"query": {
"prefix":{
"cityName":"pér"
}
}
,
"size":20
}
Then I get no result at all.
If you have any clue or help, I would be happy to know it.
Thanks
In the Prefix Query, your search input is not analyzed like in other cases:
Matches documents that have fields containing terms with a specified prefix (not analyzed)
Your first example works because the documents are analyzed at index time using your analyzer with lowercase and asciifolding, so they contain a term starting with per (perpezat, pern, pereuil).
Your second example does not work because those documents don't contain any terms starting with pér.
Since I couldn't find a way to tell Elasticsearch to analyze the prefix before performing the search, you could achieve your goal by manually adding this step:
Ask Elastisearch to analyze your input calling the Analyze API
Use the output from step 1 (it should be per in the examples) for the prefix query
For this to work, your search input should be a single term (I think that could be why Elasticsearch doesn't want to analyze it in the first place)
#mario-trucco Finally, I've found this post that explains a better way to analyze the strings.
What is an effective way to search world-wide location names with ElasticSearch?
Of course it doesn't answer my initial question and I still don't understand what happened, but it solves my problem by removing it.
Thanks again for your help and time.
I'm trying to write a query that finds articles based on their comments.
So if a user is trying to find "chocolates"
{
type: "article",
id: "myArticle1",
title: "something about brown food"
}
{
body: "I love chocolates!",
type:"comment",
commentOf: "myArticle1"
}
In this example I have both documents in the same index and I'm trying to get the "myArticle1" document via the comment matching chocolates in body. How do I do this? Is it with the top_children query?
You can use the parent-child in ES to achieve this:
Define the parent (article) and child (comment)
Index data. You should know how to index child data as it will difference from normal (need to specify parent in the index request)
Use has_child query to query for article that matched some
fields in comment
I wrote a full working sample script for it: https://gist.github.com/dqduc/efa66047358dac66461b
You can run it to test and send me your feedback. I guess you're new to ES and parent-child relationship in ES.