Im trying to search only on the following fields:
name (product name)
vendor.username
vendor.name
categories_name
But the results is to wide, I want the results to be exactly what user is typed.
Example:
I type Cloth A I want the result to be exactly Cloth A not something else contain Cloth or A
Here is my attempt:
```
GET /products/_search
{
"query": {
"filtered": {
"query": {
"multi_match": {
"query": "cloth A",
"fields": [
"name",
"vendor.name",
"vendor.username",
"categories_name"
]
}
},
"filter": [
{
"term": {
"is_available": true
}
},
{
"term": {
"is_ready": true
}
},
{
"missing": {
"field": "deleted_at"
}
}
]
}
}
}
```
How do I do that? Thanks in advance
Put this in your multi_match
"multi_match": {
"type": "best_fields"
}
This one works:
"multi_match": {
"type": "phrase"
}
Related
I was able to find this other question: Using of possessive_english stemmer in Elasticsearch
but its been 3 years since there was any activity on it
I am trying to get elasticsearch to ignore ' when indexing and searching. For example:
POST my_index/_doc/
{
"message" : "Mike's bike"
}
I want to be able to search for this document using "mikes", "mike's", "mike". I looked and thought that possessive_english should accomplish this task but I have been unable to get the expected results.
I created the index with
PUT /my_index
{
"settings": {
"analysis": {
"analyzer": {
"rebuilt_standard": {
"tokenizer": "standard",
"filter": [
"lowercase", "my_stemmer"
]
}
},
"filter": {
"my_stemmer":{
"type": "stemmer",
"language": "possessive_english"
}
}
}
}
}
I tested the analyzer with
POST /my_index/_analyze
{
"analyzer": "rebuilt_standard",
"text": "Mike's bike"
}
And this is the result
{
"tokens" : [
{
"token" : "mike",
"start_offset" : 0,
"end_offset" : 6,
"type" : "<ALPHANUM>",
"position" : 0
},
{
"token" : "bike",
"start_offset" : 7,
"end_offset" : 11,
"type" : "<ALPHANUM>",
"position" : 1
}
]
}
Looks like the analyzer is working. Then I inserted the document with:
POST my_index/_doc/
{
"message" : "Mike's bike"
}
When searching for it, it returned 0 results
GET /my_index/_search
{
"query": {
"match": {"message": "mike"}
}
}
GET /my_index/_search
{
"query": {
"match": {"message": "mikes"}
}
}
but
GET /my_index/_search
{
"query": {
"match": {"message": "mike's"}
}
}
returned results
It seems like I am missing the configuration on the mapping side of things from the linked question but I am not sure how to set it.
I tested the above with kibana but I am actually using rails and gems 'elasticsearch-model', 'elasticsearch-rails', 'elasticsearch-persistence' with the repository pattern. I am also new to rails so I don't know if its my configs with rails, or elasticsearch, or both that needs work.
I'll post them just in case
include Elasticsearch::Persistence::Repository
include Elasticsearch::Persistence::Repository::DSL
client = Elasticsearch::Client.new(url: 'http://localhost:9200', log: true)
settings index: {
number_of_shards: 1,
analysis: {
analyzer: {
custom: {
type: "custom",
tokenizer: "standard",
filter: [
"lowercase",
"english_possessive_stemmer",
]
}
},
filter: {
english_possessive_stemmer: {
type: "stemmer",
language: "possessive_english",
}
}
}
}
mappings {
indexes :icon, index: false
indexes :properties, type: 'nested' do
indexes :values
end
indexes :name
}
in the controller
repository = Repository.new
repository.create_index!(force: true)
repository.save(json)
results = repository.search(query: { match: { name: 'Mikes' } })
Your analyzer is working fine. I think you have not applied it to your mapping
PUT /my_index
{
"settings": {
"analysis": {
"analyzer": {
"rebuilt_standard": {
"tokenizer": "standard",
"filter": [
"lowercase", "my_stemmer","english_stemmer"
]
}
},
"filter": {
"my_stemmer":{
"type": "stemmer",
"language": "possessive_english"
},
"english_stemmer": {
"type": "stemmer",
"language": "english"
}
}
}
},
"mappings": {
"properties": {
"message":{
"type": "text",
"analyzer": "rebuilt_standard" ---> pass the analyzer
}
}
}
}
possessive_english filter only removes "'" , you cannot use it to search for mikes (it will work for mike though). You will need to use stemmer which reduces words to their base form.
I have an excellent article here for further reference.
man, this should be simple, but I can't get it.
I'm debugging, and just need to count the number of docs that match my filter.
GET my_index/_count
{
"query": {
"match_all": {},
"filter": {
"range": {
"published": {
"gte": "2018-02-19",
"format": "yyyy-MM-dd"
}
}
}
}
}
That's giving me
[match_all] malformed query, expected [END_OBJECT] but found [FIELD_NAME]"
I'm working with version 5.6.
You could try this one:
POST my_index/_count
{
"query": {
"bool": {
"must": [{
"match_all": {}
}],
"filter": [
{ "range": {"published": { "gte": "2018-02-19", "format": "yyyy-MM-dd"} }}
]
}
}
}
You could also get the total hits when doing a simple POST my_index/_search and filter for the needed range.
I'm migrating my elasticsearch from using facets to using aggregations, and I want to create a query where the aggregations represent all the creator names that begin with a certain letter.
I've created a nested index like so:
indexes creators, type: 'nested' do
indexes :name, type: 'string', analyzer: 'caseinsensitive', index: 'not_analyzed'
end
The following query will return all the items where a creator's name begins with a "b". Great working so far.
{
"query": {
"filtered": {
"query": {"match_all": {}},
"filter": {
"nested": {
"path": "creators",
"query": {
"prefix": {
"creators.name": {
"value": "b"
}
}
}
}
}
}
},
"aggregations": {
"creators": {
"nested": {
"path": "creators"
},
"aggs": {
"name": {
"terms": {
"field": "creators.name",
"size": 100
}
}
}
}
}
}
However, the aggregations part of the query returns ALL of the aggregations for the results, including instances creator names that do not begin with a "b." For instance, if I had an item with two creators:
"creators": [
{
"name": "Beyonce"
},
{
"name": "JayZ"
}
],
The aggregation results would include both JayZ and Beyonce. Like most people, I only want Beyonce.
Try this query and see how it goes:
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"nested": {
"path": "creators",
"query": {
"prefix": {
"creators.name": {
"value": "b"
}
}
}
}
}
}
},
"aggregations": {
"creators": {
"nested": {
"path": "creators"
},
"aggs": {
"NAME": {
"filter": {
"prefix": {
"creators.name": "b"
}
},
"aggs": {
"name": {
"terms": {
"field": "creators.name",
"size": 100
}
}
}
}
}
}
}
}
Elasticsearch's article outlines how to find objects based on a search through one generation: https://www.elastic.co/guide/en/elasticsearch/guide/current/grandparents.html
GET /company/country/_search
{
"query": {
"has_child": {
"type": "branch",
"query": {
"has_child": {
"type": "employee",
"query": {
"match": {
"hobby": "hiking"
}
}
}
}
}
}
}
What if I want to also want to query the branch for the name starting with "liverpool"? How do you modify this search to find that? I keep getting format errors and I can't seem to find information about how nest the queries online.
I've already tried this (it doesn't work):
GET /company/country/_search
{
"query": {
"has_child": {
"type": "branch",
"query": {
"has_child": {
"type": "employee",
"query": {
"match": {
"hobby": "hiking"
}
}
},
"match": {
"name": "london"
}
}
}
}
}
I got an error that said the query was malformed.
I tried bool, but it doesn't work either; I can't use has_child with a bool.
I was able to make it work with a bool query.
If I'm understanding your question correctly, this should do what you want:
POST /company/country/_search
{
"query": {
"has_child": {
"type": "branch",
"query": {
"bool": {
"must": [
{
"has_child": {
"type": "employee",
"query": {
"match": {
"hobby": "hiking"
}
}
}
},
{
"match": {
"name": "liverpool"
}
}
]
}
}
}
}
}
If you want the query to be an "OR" instead of an "AND", use "should" instead of "must".
Here is some code I set up to play around with the problem:
http://sense.qbox.io/gist/cf4babbbd25a3b7a26f3ea9ce9c1b686e37dbcb9
I have this scenario wherein there are two multi_match searches within the same query. The trouble is, when I create the JSON for it in ruby, a json with non-unique keys doesn't seem possible so only one of them appear.
Here is my query:
{
"fields": ["id", "title",
"address.city", "address.state", "address.country", "address.state_code", "address.country_code", "proxy_titles", "location"],
"size":2,
"query":{
"filtered":{
"filter": {
"range": {
"custom_score": {
"gte": 100
}
}
},
"query":{
"bool": {
"must": {
"multi_match":{
"query": "term 1",
"type": "cross_fields",
"fields": ["title^2", "proxy_titles^2","description"]
}
},
"must": {
"multi_match": {
"query": "us",
"fields": ["address.city", "address.country", "address.state",
"address.zone", "address.country_code", "address.state_code", "address.zone_code"]
}
}
}
}
}
},
"sort": {
"_score": { "order": "desc" },
"variation": {"order": "asc"},
"updated_at": { "order": "desc" }
}
}
I have also only recently started using elasticsearch so it be very helpful if you could suggest me a better query to accomplish the same as well.
You have the syntax wrong. For multiple "must" values in a "bool", they need to be in an array. The documentation is not always terribly helpful, unfortunately (the bool query page shows this for "should" but not "must").
Try this:
{
"fields": ["id","title","address.city","address.state","address.country","address.state_code","address.country_code","proxy_titles","location"],
"size": 2,
"query": {
"filtered": {
"filter": {
"range": {
"custom_score": {
"gte": 100
}
}
},
"query": {
"bool": [
{
"must": {
"multi_match": {
"query": "term 1",
"type": "cross_fields",
"fields": ["title^2","proxy_titles^2","description"]
}
}
},
{
"must": {
"multi_match": {
"query": "us",
"fields": ["address.city","address.country","address.state","address.zone","address.country_code","address.state_code","address.zone_code"]
}
}
}
]
}
}
},
"sort": {
"_score": {
"order": "desc"
},
"variation": {
"order": "asc"
},
"updated_at": {
"order": "desc"
}
}
}