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

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.

Related

Python OpenSearch retrieve records based on element in a list

So I need to retrieve records based on a field called "cash_transfer_ids" which is a python list.
I want to retrieve all records whose cash_transfer_ids contain a specific id value (a string).
What should the query be look like? Should I use match or term query?
Example: I want to retrieve any record whose cash_transfer_ids field contains 'abc'
Then I may get record such as
record 1: cash_transfer_ids:['abc']
record 2: cash_transfer_ids:['dfdfd', 'abc']
etc...
Thanks very much for any help!
if cash_transfer_ids is type keyword I try filter with Term.
term = "abc"
query = {
"query": {
"term": {
"cash_transfer_ids": {
"value": term
}
}
}
}
response = get_client_es().search(index="idx_test", body=query)

How to search for an exact value in a keyword array field in ElasticSearch?

I have a Keyword field that is an array and am trying to search for documents that contain one of the values in the array.
A document contains a field called allowed_groups:
"allow_groups" : [
"c4e3f246-0b1f-43cc-831e-37ca620bf083"
],
I have tried a match query
...
"must":[
{
"match": {
"allow_groups": {
"query": "c4e3f246-0b1f-43cc-831e-37ca620bf083"
}
}
},
...
This returns results but as soon as I change a single character (3 at the end of the value to a 4), the documents still return. I need to change the value to something much different for the documents to not return.
I have also tried a term query in its place but cant get documents to come back at all.
I also should mention that in the end I am trying to pass an array of values to be matched against the allow_groups keyword array and return a document when theres at least 1 single exact match. Im just testing with 1 value currently.

Couchbase Filter Query -> number in range between two numbers using Spring Data Couchbase (SpEL notation).)

I'm trying to make a query in a Couchbase Database. The idea is to retrieve the elements which are in the range of two numbers. I'm using Spring Data Couchbase.
My query looks like this:
#Query("#{#n1ql.selectEntity} WHERE #{#n1ql.filter} AND $age BETWEEN minAge AND maxAge ")
Optional<Room> findByMinAgeAndMaxAge(#Param("age") int age);
But
Unable to execute query due to the following n1ql errors:
{"msg":"No index available on keyspace bucketEx that matches your query. Use CREATE INDEX or CREATE PRIMARY INDEX to create an index, or check that your expected index is online.","code":4000}
This is what I get in the console:
SELECT META(`bucketEx`).id AS _ID, META(`bucketEx`).cas AS _CAS, `bucketEx`.* FROM `bucketEx` WHERE `docType` = \"com.rccl.middleware.engine.repository.model.salon\" AND $age BETWEEN minAge AND maxAge ","$age":7,"scan_consistency":"statement_plus"}
My doubt is if I have to create the indexes for the two fields ( minAge AND maxAge) or there is another issue related with my query. I'm starting with Couchbase and not pretty sure of what is happening.
My document looks like this:
{
"salons": [
{
"name": "salon_0",
"id": "salon-00",
"maxAge": 6,
"minAge": 3
}
],
"docType": "com.rccl.middleware.engine.repository.model.salon"
}
The age you are looking is inside salons array. If you want document if any one of the array object matches you should use array index on on one of the filed.
CREATE INDEX ix1 ON bucketEx(DISTINCT ARRAY v.maxAge FOR v IN salons END)
WHERE `docType` = "com.rccl.middleware.engine.repository.model.salon";
SELECT META( b ).id AS _ID, META( b ).cas AS _CAS, b.*
FROM `bucketEx` AS b
WHERE b.`docType` = "com.rccl.middleware.engine.repository.model.salon" AND
ANY v IN b.salons SATISFIES $age BETWEEN v.minAge AND v.maxAge END;

Elasticsearch Go nested query

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.

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