Reputation: 1274
All would like to use the filtered query where results should contain data from the "query_string" and also from the "term - filter" applied.
GET blog/_search
{
"query": {
"filtered": {
"query": {
"query_string": {
"fields": [ "description" ],
"query": "a" // or just ""
}
},
"filter": {
"terms": {
"topic_id": [
10
]
}
}
}
}
}
The expected result is:
So final result should be - the matching records with higher score and should come at the top, then the records just matching the "topic_id" from the filter.
Upvotes: 3
Views: 2957
Reputation: 1788
For ES 2.x
Using a bool
query should do the trick.
Here's the query I will use:
GET blog/_search
{
"query": {
"bool": {
"should": [
{
"query_string": {
"fields": [ "description" ],
"query": "a"
}
}
],
"must": [
{
"terms": {
"topic_id": [
10
]
}
}
]
}
}
}
Here, the should
clause of the bool query will tell Elassticsearch that document matching the query_string
should be returned. In the query_string
consider using wildcards if you want to match any document containing a
.
For example "query_string": { "query": "*a*" }
The must
clause in the other hand will tell that, for considering the document a valid match, it must contain 10
in the topic_id
field. Wether the should
clause could or could not match.
I hope this could help you.
Upvotes: 2
Reputation: 17441
One way to achieve this is use muti_fields mapping for description
field. One of the fields in multi-field should be non-analyzed.
Once the data has been reindexed you can use a simple bool query to achieve what you want :
Create Index:
put test
{
"mappings": {
"data" : {
"properties": {
"description" : {
"type": "string",
"fields": {
"raw" : {"type": "string","index": "not_analyzed"}
}
}
}
}
}
}
Index Data:
put test/data/1
{
"description" : "a",
"test_id" : 10
}
put test/data/2
{
"description" : "",
"test_id" : 10
}
put test/data/3
{
"description" : "hello",
"test_id" : 10
}
put test/data/4
{
"description": "a",
"test_id" : 20
}
Query:
post test/data/_search
{
"query": {
"filtered": {
"query": {
"bool": {
"disable_coord": "true",
"should": [
{
"query_string": {
"fields": [
"description"
],
"query": "a"
}
},
{
"constant_score": {
"filter": {
"term": {
"description.raw": ""
}
},
"boost": 0.2
}
},
{
"constant_score": {
"filter": {
"exists": {
"field": "description"
}
},
"boost": 0.1
}
}
]
}
},
"filter": {
"terms": {
"test_id": [
10
]
}
}
}
}
}
Results :
"hits": [
{
"_index": "test",
"_type": "data",
"_id": "1",
"_score": 0.5113713,
"_source": {
"description": "a",
"test_id": 10
}
},
{
"_index": "test",
"_type": "data",
"_id": "2",
"_score": 0.29277003,
"_source": {
"description": "",
"test_id": 10
}
},
{
"_index": "test",
"_type": "data",
"_id": "3",
"_score": 0.097590014,
"_source": {
"description": "hello",
"test_id": 10
}
}
]
Query Empty string:
{
"query": {
"filtered": {
"query": {
"bool": {
"disable_coord": "true",
"should": [
{
"query_string": {
"fields": [
"description"
],
"query": ""
}
},
{
"constant_score": {
"filter": {
"term": {
"description.raw": ""
}
},
"boost": 0.2
}
},
{
"constant_score": {
"filter": {
"exists": {
"field": "description"
}
},
"boost": 0.1
}
}
]
}
},
"filter": {
"terms": {
"test_id": [
10
]
}
}
}
}
}
Result :
"hits": [
{
"_index": "test",
"_type": "data",
"_id": "2",
"_score": 1.3416407,
"_source": {
"description": "",
"test_id": 10
}
},
{
"_index": "test",
"_type": "data",
"_id": "1",
"_score": 0.44721356,
"_source": {
"description": "a",
"test_id": 10
}
},
{
"_index": "test",
"_type": "data",
"_id": "3",
"_score": 0.44721356,
"_source": {
"description": "hello",
"test_id": 10
}
}
]
Upvotes: 2
Reputation: 1122
Have you considered using wildcard query? Check this query it will work fine for you.
all blog records having letter "a" in it with topic_id is 10.
{
"filter": {
"and": [
{
"in": {
"topic_id": [
"10"
]
}
},
{
"query": {
"filtered": {
"filter": {
"bool": {
"should": [
{
"query": {
"wildcard": {
"description": {
"value": "*a*"
}
}
}
}
]
}
}
}
}
}
]
}
}
Also rest of the records where topic_id is 10 even if the description is blank/empty. This will return all the other records that doesn't match the wildcard.
{
"filter": {
"and": [
{
"in": {
"topic_id": [
"10"
]
}
},
{
"not": {
"query": {
"filtered": {
"filter": {
"bool": {
"should": [
{
"query": {
"wildcard": {
"description": {
"value": "*a*"
}
}
}
}
]
}
}
}
}
}
}
]
}
}
To find only the empty " " description fields with topic_id 10. try this,
{
"filter": {
"and": [
{
"in": {
"topic_id": [
"10"
]
}
},
{
"query": {
"filtered": {
"filter": {
"script": {
"script": "_source.description.length() == 0"
}
}
}
}
}
]
}
}
Upvotes: 2