Elasticsearch order by type - elasticsearch

I'm searching an index with multiple types by simply using 'http://es:9200/products/_search?q=sony'. This will return a lot of hits with many different types. The hits array contains all the results but not in the order I want it to; i want the 'television' type to always show before the rest. Is it possible at all to order by type?

You can achieve this by sorting on the pre-defined field _type. The query below sorts results in ascending order of document types.
POST <indexname>/_search
{
"sort": [
{
"_type": {
"order": "asc"
}
}
],
"query": {
<query goes here>
}
}

I do it by adding a numeric field _is_OF_TYPE to the indexed documents and set it to 1 for those docs that are of the given type. Then just sort on those fields in any order you want.
For example:
Document A:
{
_is_television: 1,
... some television props here ...
}
Document B:
{
_is_television: 1,
... another television props here ...
}
Document C:
{
_is_radio: 1,
... some radio props here ...
}
and so on...
Then in ElasricSearch query:
POST radio,television,foo,bar,baz/_search
{
"sort": [
{"_is_television": {"unmapped_type" : "long"}}, // television goes first
{"_is_radio": {"unmapped_type" : "long"}}, // then radio
{"_is_another_type": {"unmapped_type" : "long"}} // ... and so on
]
}
The benefit of this solution is speed. You simply sort on numeric fields. No script sorting required.

Related

Elasticsearch agg filter using an array of values

{ "colors":["red","black","blue"] }
{ "colors":["red","black"] }
{ "colors":["red"] }
{ "colors":["orange, green"] }
{ "colors":["purple"] }
How can I run an agg that filters for specific values contained in the array field?
For example, I only want the count of "red" and wish to exclude its other siblings from the aggregation result.
Note: I cannot use an "include" pattern for "red". This example is simplistic, the real-world example has a long list of string values that are unique.
I would like to filter the agg using an array of string values.
From docs
For matching based on exact values the include and exclude parameters can simply take an array of strings that represent the terms as they are found in the index:
{
"aggs": {
"colors": {
"terms": {
"field": "colors",
"include": [ "red","black" ]
}
}
}
}

Custom sort lexicographically as int

I have some elastic elements that have a string property that looks like 10/2021 and it need to be sorted as a int, but when I perform this query
"sort": [
{
"myProperty": {
"order": "asc"
}
},
I get the lexicographic order.
1/2021
10/2021
100/2021
101/2021
102/2021
But I need it to sort by the first number and the year like this:
1/2020
2/2020
...
1/2021
2/2021
I can't figure out how to custom sort, is it even possible?
Solution 1:
Using Scripted-Sort ...
Not Recommended with large data-set: It will take time as we are performing computations here
GET <>/_search
{
"query": {
"match_all": {}
},
"sort": {
"_script":{
"type":"number",
"script":{
"lang":"painless",
"source":"Integer.parseInt(doc['myProperty.keyword'].value.replace(\"/\",\"\"))" //<====== Replace myProperty.keyword with the keyword field or String field with field-data true
}
}
}
}
Note: i haven't added null checks in the script, just in case you have any document which don't have this field.
Solution 2:
Store another Numeric field in elastic search which doesn't have "/"
Sort based on that field
Migrate the data of existing documents to the field using update_by_query API
This is the Recommended approach.

Elasticsearch: sort by copy_to target of two fields

I'm using trying to create a fullName using copy_to exactly like docs say to do: https://www.elastic.co/guide/en/elasticsearch/reference/current/copy-to.html
But, what I want to do in a query, is to sort by fullName. However, when I specify the field to sort I see that the query is actually sorted by forename, e.g. the first part of copy_to:
{
"sort": [
{
"<nested>.fullName.keyword": {
"nested_path": "<nested>",
"order": "desc"
}
}
]
}
What I want to do is to sort by forename + surname e.g. by full fullName.
Is it possible to do this using copy_to at all?

Query against array of long types returns nothing

I have a cluster with documents, with one field being an array of long types. Below is an example value of this field:
"request_categories": [
150848602323501540,
150847029425938900
],
When I query the field, it does not return anything. Below is the query.
GET service_alias/service/_search
{
"query": {
"term": {
"request_categories" : 150848602323501540
}
}
}
This data field is indexed. I have no problems querying other data fields. Anything that I may have missed? Thanks!

Elsticsearch : Contains query

I have a column in my mapping that holds an array of strings
col1
["asd","fgh","wer"]
["qwer","cvbvbn","popop"]
["cvbml","fhjhfrjk","fsdfd"]
["asd","trth","fdf"]
The column col is not analyzed in the index and i do not want to change the mapping.
"col1":
{
"type":"string",
"index":"not_analyzed"
}
Now, i want to retrieve all records where the string asd appears. so in this case, i want the first and fourth records. I tried using the query
query: {
wildcard:{
"col1":"asd"
}
}
with
POST localhost:9200/indexName/test/_search
but that gives me empty results? Which query should i use in this case?
Edit
So i was able to solve the above problem. Here is a follow up. Consider that this was my data
col1
["asd fd","fgh bn","wer kl"]
["qwer","cvbvbn","popop"]
["cvbml","fhjhfrjk wewe","fsdfd rtr"]
["asd","trth","fdf"]
so now, the array contains some strings that have multiple words. Now, i still want to return the first and fourth record. If i go with the solution that i posted, i only get the fourth one. How can i apply the contains logic to each element of the array in col1?
Note
A partial solution is
{ "query": { "match_phrase_prefix": { "col1": "asd" } } }
so again, for the data
col1
["asd fd","fgh bn","wer kl"]
["qwer","cvbvbn","popop"]
["cvbml","fhjhfrjk wewe","fsdfd rtr"]
["asd","trth","fdf"]
it returns the first and fourth records. However, if i have
col1
["fd asd","fgh bn","wer kl"]
["qwer","cvbvbn","popop"]
["cvbml","fhjhfrjk wewe","fsdfd rtr"]
["asd","trth","fdf"]
then, once again it only returns the fourth one, which is understandable as now, asd is no longer a prefix for that value in the first record.
Is there a way to to a contains type match instead of just prefix match?
You can use a simple term query and it should work
POST localhost:9200/indexName/test/_search
{
"query": {
"terms": { "col1" : "asd" }
}
}
so, here is the proper query
{
fields : ["col1","col2"],
query: {
filtered: {
query: {
match_all: {}
},
filter: {
terms: {
col1: ["asd"]
}
}
}
}
}
Final Answer
query: {
wildcard:{
col1:{
value:"*asd*"
}
}
}
:)

Resources