Elasticsearch Go nested query - elasticsearch

I'm using olivere's elastic Go library to run Elastic queries - https://godoc.org/github.com/olivere/elastic#NestedQuery
The data I'm trying to query on looks like this:
"_source": {
"field1": "randVal1",
"field2": "randVal2",
"nestedfield": {
"ind1": "val1"
}
}
I'm trying to run a query on the nestedfield using the NestedQuery call from the Elastic Go library like so:
aquery := elastic.NewTermQuery("ind1", "val1")
query := elastic.NestedQuery("nestedfield", aquery)
But I get an error stating:
too many arguments to conversion to NestedQuery
I'm trying to retrieve all documents where the ind1 of nestedfield is val1. Would appreciate any help in constructing this query.
EDIT:
I changed it to NewNestedQuery and now it doesn't give that error. However, it is not returning any results, even though that document exists in the index and I am able to query on the non-nested fields.
I tried this:
aquery := elastic.NewTermQuery("ind1", "val1")
query := elastic.NewNestedQuery("nestedfield", aquery)
And this:
query := elastic.NewNestedQuery("nestedfield", elastic.NewMatchQuery("nestedfield.ind1", "val1"))
But they both give 0 results. Any idea what I'm doing wrong?
EDIT #2
The mapping is:
"field1": { "type": "string" },
"field2": { "type": "string" },
"nestedfield": {
"type": "nested"
}
What eventually worked was this:
query := elastic.NewMatchQuery("nestedfield.ind1", "val1")
I was able to add additional fields to 'nestedfield' and do queries like:
query := elastic.NewBoolQuery().Filter(elastic.NewMatchQuery("nestedfield.ind1", "val1"), elastic.NewMatchQuery("nestedfield.ind2", "val2"))

Looks like that should be:
q := elastic.NewTermQuery("nestedfield.ind1", value)
nq := elastic.NewNestedQuery("nestedfield", q)
NestedQuery is a type, not a function.
NewTermQuery needs to take a
value from the json, not a const string
You'll need to parse your source json to get the value from ind1
Edited to fix NewTermQuery too as per comments below. If that still doesn't work provide the full code you're using to parse source and get the error as you don't give enough detail here to guess at the problem.

Related

How can I combine multimatch query with a boolquery in elasticsearch?

I am trying to write a query that will run a query coupled with a multimatch query (possibly with an empty value) in elasticsearch. Consider the following data example where each item is a document in elasticsearch. Additional fields are redacted to reduce complexity in the example.
[
{
"name": "something",
"categories": ["python", "lib"]
},
{
"name": "test",
"categories": ["python", "lib"]
},
{
"name": "another",
"categories": ["javascript", "lib"]
}
]
What I am trying to do is writing a bool query where categories must match python and lib, and then run a multimatch query on that. So my code structure is:
// assume cat.Filter folds []string{"python", "lib"}
filters := []elastic.Query{}
for _, ff := range cat.Filter {
filters = append(filters, elastic.NewTermQuery("categories", ff))
}
// create multimatch query
e := elastic.NewMultiMatchQuery("something").Fuzziness("2")
// create a query that will match all fields in an array
q := elastic.NewBoolQuery().Must(filters...).Filter(e)
hits, err := client.Search().Index(index).Query(q).Size(limit).Do(ctx)
If I run this query with as is, then I get back 1 hit as expected. But if I change the multimatch query to e := elastic.NewMultiMatchQuery("some"), then I get back an empty array.
What I am trying to accomplish is:
When using e := elastic.NewMultiMatchQuery("some").Fuzziness("2"), return an array of 1 item that matches something
When I set e := elastic.NewMultiMatchQuery("").Fuzziness("2"), return an array of two items that match both categories for python and lib. (this works if i remove the multimatch array filter.
My issue is that I can do either or, but not both. I have a feeling because the Must is enforcing that something has to be an exact match, and some or "" does not match that. Thats what I am trying to overcome. First match all the values in an array, and then query that.

QueryDSL _id query within script

I am using Elasticsearch & Kibana v5.6 and within devTools, I am able to use script within querydsl to query for a doc on a fieldname = value, ie:
GET indexA/_search
{
"query":{ "script":{ "script": """
def a = doc['field1'].value;
return a == 'value1';
"""}}
}
Above would return all doc that has 'value1' as value within the field called 'field1'. But I am unable to search on _id, official doc says that prior to v6 we should use _uid instead so I have tried that with no luck. I am using script because after I am able to use _uid to get value of _id, essentially I want to do some value comparison similar to below:
GET indexA/_search
{
"query":{ "script":{ "script": """
def a = doc['field1'].value;
def b = doc['_uid'].value;
return a == b;
"""}}
}
I think devTools is where i want to execute this instead of other places. Any pointers are appreciated
You are referring to Query Id's document or this one but deploying in the wrong context you need to define id's in the separate head of ids or put under term field _id.

Merge Documents based on field value?

I have multiple Documents within an Index, each have the following fields:
id serviceName Type
Now, stupidly, id is not unique and I want to change that. I want to use Kibana/Elasticsearch to query the data so that I have id unique and the behaviour I want is that if I have the following Docs:
id serviceName Type
1 A T1
1 B T2
1 D T2
I use a query so that I get this result
1 A,B,C T1,T2,T3
Is there a way for this?
You cannot do this with just Elasticsearch/Kibana, you have to write some code. You can use the scroll api to iterate through all the documents in the index, and then use an upsert query to index them into a new index. I think your upsert request will look something like this:
POST test/type1/1/_update
{
"script" : {
"inline": "ctx._source.serviceName.add(params.serviceName); ctx._source.Type.add(params.Type)",
"lang": "painless",
"params" : {
"serviceName" : "A",
"Type": "T1"
}
},
"upsert" : {
"serviceName": ["A"],
"Type": ["T1"]
}
}
This means in case id 1 doesn't exist yet, add it with the "upsert" value for the document, otherwise do the script (which appends the serviceName and Type values to the existing doc).
This would be pretty straightforward to do with very little code using elasticsearch-py, check out the scan helper and bulk helper

ElasticSearch: Return the query within the response body when hits = 0

Please note that the following example is a very minified version of a real life use case, it is for the question to be easy to read and to make a point.
I have the following document structure:
{
"date" : 1400500,
"idc" : 1001,
"name": "somebody",
}
I am performing an _msearch query (multiple searchs at a time) based on different values (the "idc" and a "date" range)
When ES could not find any documents for the given date range it returns:
"hits":{
"total":0,
"max_score":null,
"hits":[
]
}
But, since there are N results, I cannot tell which "idc" and what "date" range was this result for.
I would like the response to have the "searched" date range and "idc" when there are no results for the given query. for example, if I am searching documents for IDC = 1001 and date between 1400100 and 1400200, but there are no results found, the response should have the query terms in the response body, something like this:
"hits":{
"total":0,
"max_score":null,
"query": {
"date": {
"gt": 1400100,
"lte": 1400200,
}
"idc": 1001,
}
}
That way I can tell what date range and "idc" combination has no results.
Please note that the above example is a very minified version of a real life use case, it is for the question to be easy to read and to make a point.
This is from the docs
multi search API(_msearch) response returns a responses array, which includes the search
response and status code for each search request matching its order in
the original multi search request.
since you know the order in which you sent the requests , you can find out which request failed.
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-multi-search.html

String range query in Elasticsearch

I'm trying to query data in an Elasticsearch cluster (2.3) using the following range query. To clarify, I'm searching on a field that contains an array of values that were derived by concatenating two ids together with a count. For example:
Schema:
{
id1: 111,
id2: 222,
count: 5
}
The query I'm using looks like the following:
Query:
{
"query": {
"bool": {
"must": {
"range": {
"myfield": {
"from": "111_222_1",
"to": "111_222_2147483647",
"include_lower": true,
"include_upper": true
}
}
}
}
}
}
The to field uses Integer.MAX_VALUE
This works alright but doesn't exactly match the underlying data. Querying through other means produces more results than this method.
More strangely, trying 111_222_5 in the from field produces 0 results, while trying 111_222_10 does produce results.
How is ES (and/or Lucene) interpreting this range query and why is it producing such strange results? My initial guess is that it's not looking at the full value of the last portion of the String and possibly only looking at the first digit.
Is there a way to specify a format for the TermRange? I understand date ranging allows formatting.
A look here provides the answer.
The way it's doing range is lexicographic, 5 comes before 50 comes before 6, etc.
To get around this, I reindexed using a fixed length string for the count.
0000000001
0000000100
0001000101
...

Resources