Exists query for objects inside fields - elasticsearch

https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-exists-query.html says that it is possible to query for documents that have at least one non-null value in the original field.
If the value of the original fields is an object, is it possible to query for the existence of a key in the object?
Example: a document is
{
"user": {
"name": "XY",
"passport_id": 1234
}
}
Can one make an exists query for user.name? I tried
{
"query": {
"exists" : { "field" : "user.name" }
}
}
but it does not give any results.

Related

Search for empty/present arrays in elasticsearch

I'm currently using the elasticsearch 6.5.4 and I'm trying to query for all docs in an index with an empty array on a specific field. I found the the elasticsearch has a exists dsl who is supposed to cover the empty array case.
The problem is: whem I query for a must exists no doc is returned and when I query for must not exists all documents are returned.
Since I can't share the actual mapping for legal reasons, this is the closest I can give you:
{
"foo_production" : {
"mappings" : {
"foo" : {
"properties" : {
"bar" : {
"type" : "text",
"index" : false
}
}
}
}
}
}
And the query I am performing is:
GET foo_production/_search
{
"query": {
"bool": {
"must": {
"exists": {
"field": "bar"
}
}
}
}
}
Can you guys tell me where the problem is?
Note: Upgrading the elasticsearch version is not a viable solution
Enable indexing for the field bar by setting "index" : true
The index option controls whether field values are indexed. It accepts true or false and defaults to true. Fields that are not indexed are not queryable.
Source : https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-index.html

Elasticsearch: conditionally sort on 2 fields, 1 replaces the other if it exists

Without scripting, I need to sort records based on rating. The system-rating exists for all records, but a user-rating may or may not exist. If a user-rating does exist I want to use that value in the sort instead of the system-rating, for that particular record and only for that record.
Tried looking into the missing setting but it only allows _first, _last or a custom value (that will be used for missing docs as the sort value):
{
"sort" : [
{ "user_rating" : {"missing" : "_last"} },
],
"query" : {
"term" : { "meal" : "cabbage" }
}
}
...but is there a way to specify the custom value should be system_rating when user_rating is missing?
I can do the following:
query_hash[:sort] = []
if user_rating.exist?
query_hash[:sort] << {
"user_rating" => {
"order": sort_direction,
"unmapped_type": "long",
"missing": "_last",
}
}
end
query_hash[:sort] << {
"system_rating" => {
"order": sort_direction,
"unmapped_type": "long",
}
}
...but that will always sort user rated records on top regardless of the user_rating value.
I know that scripting will allow me to do it but we cannot use scripting. Is it possible?
The only way is scripting or building a custom field at indexing time that will contain the already built value for sorting.

Combination of and or elasticsearch

How to write query for following condition in elasticsearch
Select * from table1 where (cnd1 or cond2) and (cnd3)
My cond2 value is from nested object . My json object is below
details={ "name"="name1",
"address":"{
"city":"city1"
}"
}
I need to take city from above object
details.address.city
Is above syntax is right , if not how to get value of second object city.
{
"bool" : {
"must" : cond3,
"should" : [
cond1,
cond2
],
"minimum_should_match" : 1
}
}
go through this link for more info https://www.elastic.co/guide/en/elasticsearch/reference/2.3/query-dsl-bool-query.html
You can easily create a conditional queries with Elasticsearch. But there is some weird situation of your data section.
details={ "name"="name1",
"address":"{
"city":"city1"
}"
}
Elasticsearh save your data as a json object, but you should give your data as a json. In this section, there is an object, you try to sent. Let us examine:
There is a name attribute of detail object, it is a string. And also there is a address attribute, and it is a string too. It should be an object which has to include a city attribute if you want to reach this object via details.address.city. Now we try to fix:
{
"id":...,
...
"details": {
"name": "name1",
"address": {
"city": "city1"
}
}
}
In this case, I remove double quotation marks of details object. Now, you can reach city attribute of json as a json object. Now, we create a query to reach cities:
{
"query": {
"bool": {
"must": {
"term": {
"your-json-attribute": "???"
}
},
"should": [
{
"term": {
"your-json-attribute": "???"
}
},
{
"term": {
"your-json-attribute": "???"
}
}
]
}
}
}
I use term query but there is lots of another query types. You can check them on documentation. But for And and Or, you can use bool query. Check https://www.elastic.co/guide/en/elasticsearch/reference/2.0/query-dsl-bool-query.html

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*"
}
}
}
:)

Check for id existence in param Array with Elasticsearch custom script field

Is it possible to add a custom script field that is a Boolean and returns true if the document's id exists in an array that is sent as a param?
Something like this https://gist.github.com/2437370
What would be the correct way to do this with mvel?
Update:
Having trouble getting it to work as specified in Imotov's answer.
Mapping:
Sort:
:sort=>{:_script=>{:script=>"return friends_visits_ids.contains(_fields._id.value)", :type=>"string", :params=>{:friends_visits_ids=>["4f8d425366eaa71471000011"]}, :order=>"asc"}}}
place: {
properties: {
_id: { index: "not_analyzed", store: "yes" },
}
}
I don't get any errors, the documents just doesn't get sorted right.
Update 2
Oh, and I do get this back on the documents:
"sort"=>["false"]
You were on the right track. It just might be more efficient to store list of ids in a map instead of an array if this list is large.
"sort" : {
"_script" : {
"script" : "return friends_visits_ids.containsKey(_fields._id.value)",
"type" : "string",
"params": {
"friends_visits_ids": { "1" : {}, "2" : {}, "4" : {}}
}
}
}
Make sure that id field is stored. Otherwise _fields._id.value will return null for all records.

Resources