I was doing search using elastic search using the code:
es.search(index="article-index", fields="url", body={
"query": {
"query_string": {
"query": "keywordstr",
"fields": [
"text",
"title",
"tags",
"domain"
]
}
}
})
Now I want to insert another parameter in the search scoring - "recencyboost".
I was told function_score should solve the problem
res = es.search(index="article-index", fields="url", body={
"query": {
"function_score": {
"functions": {
"DECAY_FUNCTION": {
"recencyboost": {
"origin": "0",
"scale": "20"
}
}
},
"query": {
{
"query_string": {
"query": keywordstr
}
}
},
"score_mode": "multiply"
}
}
})
It gives me error that dictionary {"query_string": {"query": keywordstr}} is not hashable.
1) How can I fix the error?
2) How can I change the decay function such that it give higher weight to higher recency boost?
You appear to have an extra query in your search (giving a total of three), which is giving you an unwanted top-level. You need to remove the top-level query and replace it with function_score as the top level key.
res = es.search(index="article-index", fields="url", body={"function_score": {
"query": {
{ "query_string": {"query": keywordstr} }
},
"functions": {
"DECAY_FUNCTION": {
"recencyboost": {
"origin": "0",
"scale": "20"
}
}
},
"score_mode": "multiply"
})
Note: score_mode defaults to "multiply", as does the unused boost_mode, so it should be unnecessary to supply it.
You cant use dictionary as a key in the dictionary. You are doing this in the following segment of the code:
"query": {
{"query_string": {"query": keywordstr}}
},
Following should work fine
"query": {
"query_string": {"query": keywordstr}
},
use it like this
query: {
function_score: {
query: {
filtered: {
query: {
bool: {
must: [
{
query_string: {
query: shop_search,
fields: [ 'shop_name']
},
boost: 2.0
},
{
query_string: {
query: shop_search,
fields: [ 'shop_name']
},
boost: 3.0
}
]
}
},
filter: {
// { term: { search_city: }}
}
},
exp: {
location: {
origin: { lat: 12.8748964,
lon: 77.6413239
},
scale: "10000m",
offset: "0m",
decay: "0.5"
}
}
// score_mode: "sum"
}
Related
I want to search text inside fields.
I tried to fix my problem from this documentation
One of my index contains items which structure is the following:
{
url: "https://exampleurl.com"
username: "some_username"
}
Here is my querys:
"query": {
"multi_match": {
"query": keyword,
"type": "phrase",
"fields": [ "username", "url" ]
}
}
Also bool query:
"query": {
"bool": {
"must": {
"multi_match": {
"query": keyword,
"type": "phrase",
"fields": [ "username", "url" ]
}
},
}
}
"query": {
"bool": {
"must": [{
"match": {
"username": keyword,
}
}, {
"match": {
"url": keyword
}
}]
}
}
But result is a empty array
please try the below query.
Create Index
PUT test
{
"settings" : {
"number_of_shards" : 1
},
"mappings" : {
"properties" : {
"url" : { "type" : "text" },
"username" : { "type" : "text" }
}
}
}
Insert Document
PUT test/_doc/1
{
"url" : "https://exampleurl.com",
"username" : "Arjun Das"
}
Search
GET test/_search
{
"query": {
"multi_match": {
"query": "http",
"type": "best_fields",
"fields": [ "username", "url" ],
"fuzziness":"2"
}
}
}
Suppose within my Elasticsearch I have a field 'ListNames' that provides a list of dictionaries. One of the keys within each dictionary is 'People'. My goal is to Query/Filter from ES all relevant profiles where 'ListNames.People' contains 'Adam' and contains a name that is NOT 'Adam'. Without a verbose list of all possible Names (since there are many), how could I achieve this? Thank you for any help in advance.
The below Code shows examples of post's I have tried
#Note: this returns profiles with ONLY Adam contained in the ListNames.
post_data = {
"size": 30,
"query": {
'match':{
'ListNames.People':'Adam'
}
}
}
#################
post_data = {
"size": 30,
"query": {
'bool': {
'should': [{
'match': {
'ListNames.People': 'Adam'
}
}],
'must_not':[
{'match':{'ListNames.People':'Adam'}}
]
}
}
}
###################
post_data = {
"size": 30,
"query": {
'bool': {
'must': [{
'match': {
'ListNames.People': 'Adam'
}
}],
'must_not':[
{'match':{'ListNames.People':'Adam'}}
]
}
}
}
The first post returns results only containing Adam, which is not desired, and the other two return empty.
Update after discussion in comments
You have to use painless to check such condition. Please note that using script can have performance degradation.
The query will be:
{
"query": {
"bool": {
"filter": [
{
"term": {
"ListNames.People": "Adam"
}
},
{
"script": {
"script": {
"source": "for(int i = 0; i < doc['ListNames.People'].length; i++) { if(doc['ListNames.People'][i] != params.person) { return true; }} return false;",
"lang": "painless",
"params": {
"person": "Adam"
}
}
}
}
]
}
}
}
I have a elastic search index collection like below,
"_index":"test",
"_type":"abc",
"_source":{
"file_name":"xyz.ex"
"metadata":{
"format":".ex"
"profile":[
{"date_value" : "2018-05-30T00:00:00",
"key_id" : "1",
"type" : "date",
"value" : [ "30-05-2018" ]
},
{
"key_id" : "2",
"type" : "freetext",
"value" : [ "New york" ]
}
}
Now I need to search for document by matching key_id to its value. (key_id is some field whose value is stored in "value")
Ex. For key_id='1'field, if it's value = "30-05-2018" it should match the above document.
I tried mapping this as a nested object, But I am not able to write query to search with 2 or more key_id matching its respective value.
This is how I would do it. You need to AND together via bool/filter (or bool/must) two nested queries for each of the condition pair, since you want to match two different nested elements from the same parent document.
{
"query": {
"bool": {
"filter": [
{
"nested": {
"path": "metadata.profile",
"query": {
"bool": {
"filter": [
{
"term": {
"metadata.profile.f1": "a"
}
},
{
"term": {
"metadata.profile.f2": true
}
}
]
}
}
}
},
{
"nested": {
"path": "metadata.profile",
"query": {
"bool": {
"filter": [
{
"term": {
"metadata.profile.f1": "b"
}
},
{
"term": {
"metadata.profile.f2": false
}
}
]
}
}
}
}
]
}
}
}
I'd like to "translate" a string like:
A AND (C OR B) AND NOT D
into an Elasticsearch query like:
{
"query": {
"bool": {
"must": {
"term": {
"text": "A"
}
},
"must_not": {
"term": {
"text": "D"
}
},
"should": [
{
"term": {
"text": "B"
}
},
{
"term": {
"text": "C"
}
}
],
"minimum_should_match": 1,
"boost": 1
}
}
}
does exists some library which I can use ?
any help appreciated
Thanks!
ok according to:
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html
I can do query like:
{
"query": {
"query_string" : {
"default_field" : "text",
"query" : (this AND (submitted OR flowers) AND NOT blight"
}
}
}
which works great.
I am using Python to query Elasticsearch with a custom query. Let's look at a very simple example that will search for a given term in the field 'name' and another one in the 'surname' field of the document:
from elasticsearch import Elasticsearch
import json
# read query from external JSON
with open('query.json') as data_file:
read_query= json.load(data_file)
# search with elastic search and show hits
es = Elasticsearch()
# set query through body parameter
res = es.search(index="test", doc_type="articles", body=read_query)
print("%d documents found" % res['hits']['total'])
for doc in res['hits']['hits']:
print("%s) %s" % (doc['_id'], doc['_source']['content']))
'query.json'
{
"query": {
"bool": {
"should": [
{
"match": {
"name": {
"query": "Star",
"boost": 2
}
}
},
{
"match": {
"surname": "Fox"
}
}
]
}
}
}
Now, I am expecting the input of search words from the user, the first word that is typed in is used for the field 'name' and the second one for 'surname'. Let's imagine I will replace the {$name} and {$surname} with the two words that have been typed in by the user using python:
'query.json'
{
"query": {
"bool": {
"should": [
{
"match": {
"name": {
"query": "{$name}",
"boost": 2
}
}
},
{
"match": {
"surname": "{$surname}"
}
}
]
}
}
}
Now the problem arises when the user doesn't input the surname but only the name, so I end up with the following query:
'query.json'
{
"query": {
"bool": {
"should": [
{
"match": {
"name": {
"query": "Star",
"boost": 2
}
}
},
{
"match": {
"surname": ""
}
}
]
}
}
}
The field "surname" is now empty and elasticsearch will look for hits where "surname" is an empty string, which is not what I want. I want to ignore the surname field if the input term is empty. Is there any mechanism in elasticsearch to set a part of query to be ignored if the given term is empty?
{
"query": {
"bool": {
"should": [
{
"match": {
"name": {
"query": "Star",
"boost": 2
}
}
},
{
"match": {
"surname": "",
"ignore_if_empty" <--- this would be really cool
}
}
]
}
}
}
Maybe there is any other way of generating query strings? I can't seem to find anything about query generation in Elasticsearch. How do you guys do it? Any input is welcome!
Python DSL seems to be the proper way of doing it https://github.com/elastic/elasticsearch-dsl-py/