First letter match in elasticsearch aggregations - ruby-on-rails

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
}
}
}
}
}
}
}
}

Related

elastic search parsing_exception for boost query

I'm trying to boost up the query using elastic search. Headlines that are published recently must be boosted up and should come on top. However, I have return the following code:
{
"query": {
"function_score": {
"query": {
"bool": {
"must": {
"match": {
"keywords": {
"query":"trump"
}
}
},
"should": [
{ "match": {
"type": {
"query": "headline"
}
}}
]}},
"functions": [
{ "boost": 5 },
{
"gauss": {
"versioncreated": {
"origin": "now/d",
"scale": "50w",
"offset": "4w",
"decay": "0.5"
}}}],
"score_mode": "sum"
}
}}
I'm getting this error :-
{
"error": {
"root_cause": [
{
"type": "parsing_exception",
"reason": "no [score_function] registered for [params]",
"line": 24,
"col": 20
}
],
"type": "parsing_exception",
"reason": "no [score_function] registered for [params]",
"line": 24,
"col": 20
},
"status": 400
}
You query is a bit wrong. What do you want do by this?
"functions": [
{ "boost": 5 },
If you want to boost it try to use this query
{
"query": {
"function_score": {
"query": {
"bool": {
"must": {
"match": {
"keywords": {
"query": "trump"
}
}
},
"should": [
{
"match": {
"type": {
"query": "headline"
}
}
}
]
}
},
"functions": [
{
"gauss": {
"versioncreated": {
"origin": "now/d",
"scale": "50w",
"offset": "4w",
"decay": "0.5"
}
}
}
],
"boost": 5,
"score_mode": "sum"
}
}
}

Rails 4 elasticsearch using multiple search conditions, combine search feature

i'm using elasticsearch-rails for a project, there is a combine search feature, all columns are in one table. I just write a custom search function, and the search dsl didn't work, can't have any results.
def self.combine_search_filter(remark=nil, sim_card_supplier_id=nil, work_mode=nil, operator_status=nil, platform_management_status=nil, online_status=nil, sim_card_set_id=nil, iccid_from=nil, iccid_to=nil, actived_at_from=nil, actived_at_to=nil, check_in_at_from=nil, check_in_at_to=nil, device_mac_from=nil, device_mac_to=nil)
response = __elasticsearch__.search(
"size": 1000,
"query": {
"filtered": {
"filter": {
"bool": {
"filter": [
{ "term": { "sim_card_supplier_id": sim_card_supplier_id } },
{ "term": { "work_mode": work_mode } },
{ "term": { "operator_status": operator_status } },
{ "term": { "platform_management_status": platform_management_status } },
{ "term": { "online_status": online_status } },
{ "term": { "sim_card_set_id": sim_card_supplier_id } }
{ "range": { "iccid": { "from": iccid_from, "to": iccid_to }}},
{ "range": { "check_in_at": { "from": check_in_at_from, "to": check_in_at_to }}},
{ "range": { "actived_at": { "from": actived_at_from, "to": actived_at_to }}},
{ "range": { "device_mac": { "from": device_mac_from, "to": device_mac_to }}}
]
}
}
}
}
)
end
and the params maybe pass nil, how can i do that make the search dsl valid?
I would rather suggest you to use searchkick gem for rails which makes elastic search as simple as that and makes your search more intelligent and queries simple.
My bad, i just figure this out, ruby keyword function should be like this:
def self.combine_search_filter(options = {})
response = __elasticsearch__.search(
"size": 1000,
"query": {
"filtered": {
"filter": {
"bool": {
"filter": [
{ "term": { "sim_card_supplier_id": 104 } },
{ "term": { "work_mode": options[:work_mode] } },
{ "term": { "operator_status": options[:operator_status] } },
{ "term": { "platform_management_status": options[:platform_management_status] } },
{ "term": { "online_status": options[:online_status] } },
{ "term": { "sim_card_set_id": 76 } },
{ "range": { "iccid": { "from": options[:iccid_from], "to": options[:iccid_to] }}},
{ "range": { "check_in_at": { "from": options[:check_in_at_from], "to": options[:check_in_at_to] }}},
{ "range": { "actived_at": { "from": options[:actived_at_from], "to": options[:actived_at_to] }}},
{ "range": { "device_mac": { "from": options[:device_mac_from], "to": options[:device_mac_to] }}}
]
}
}
}
}
)
end
this search will have the correct result. The options[:key] may be nil will cause the wrong result, so i'm gonna delete the nil key of the dsl hash, then pass it to search()

Elasticsearch exact match only for specific fields on multi_match fields

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"
}

Elasticsearch DSL with multiple multi_match query in ruby

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"
}
}
}

How join parent and child in elasticsearch

How join parent and child in elasticsearch?
For example my mapping:
{
"street":{
"properties":{
"street_name":{
"type":"string"
}
}
}
}
and
{
"address":{
"_parent":{
"type":"street"
},
"properties":{
"house_number":{
"type":"string"
}
}
}
}
Data:
{"_type":"street","_id":"AUrLQH9ZcB6int_hskH3","_source":{"street_name":"Street"}}
{"_type":"address","_id":"AUrLQH_XcB6int_hskH4","_source":{"house_number":"10"}}
How i can get similar result in one query:
{
"_type":"address",
"_id":"AUrLQH_XcB6int_hskH4",
"house_number":"10",
"street_name":"Street"
}
Of course, for a single element, i can join types in application, but what to do with large lists?
Thanks!
Maybe something like this, don't think there is a way of grouping them nicely:
GET /postal_codes/street/_search?search_type=count
{
"aggs": {
"street": {
"terms": {
"field": "street_name"
},
"aggs": {
"addresses": {
"children": {
"type": "address"
},
"aggs": {
"number": {
"terms": {
"field": "address.house_number"
}
}
}
}
}
}
}
}

Resources