so i have a index for my map points and i need to put some data in it. but it seems it does not register my data as a valid input for pin.location .
I have tried all i could get from https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-geo-distance-query.html
and still this does not work
This is where i set the index:
mappings = {
"mappings": {
"properties": {
"pin": {
"properties": {
"location": {
"type": "geo_point"
}
}
},
"index.mapping.single_type": False
}
}
}
es = Elasticsearch([{'host': 'localhost', 'port': 9200}])
if not es.indices.exists(index="groups_map"):
es.indices.create(index='groups_map', body=mappings)
es.index(index='groups_map', id=data["id"], doc_type='groups_map', body=data, request_timeout=30)
here is data:
data = {
"pin": {
"properties": {"location": {
"type": "geo_point",
'lat': request.POST['source_lat'],
'lon': request.POST['source_lon']}
}
},
"id": instance.id,
}
and this is my query data here is just a dictionary with lat and lon values
query = {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_distance": {
"distance": "12km",
"pin.location": {
"lat": data["lat"],
"lon": data["lon"]
}
}
}
}
}
return es.search(index="groups_map", body={"query": query}, size=20)
this is the full error i get:
elasticsearch.exceptions.RequestError: RequestError(400, 'search_phase_execution_exception', 'failed to find geo_point field [pin.location]')
The problem is that your data is not correct as you need to remove the properties key. Your data should look like this.
data = {
"pin": {
"location": {
'lat': request.POST['source_lat'],
'lon': request.POST['source_lon']
}
},
"id": instance.id,
}
Note: You need to delete and recreate your index before indexing new data.
Related
I have the following document structure.
{
_id: ...,
unique_id: 1234,
config_no: 1,
configs: [
{
data: "qwertyuiop" // random string
},
{
data: "asdfghjkl" // random string
}
]
}
I want to update value of data from one of the configs. The index of the config that needs to be updated is available in the config_no key.
Is there any way to update the value without querying the document.
This is what I am currently doing
doc = db.collection.findOne({"unique_id": 1234})
config_no = doc.config_no
db.collection.updateOne(
{"unique_id": 1234},
{"$set": {"configs."+config_no+".data": "zxcvbnm"}} //"configs.1.data"
)
Following is something what i would like to achive.
db.collection.updateOne(
{"unique_id": 1234},
{"$set": {"configs.${config_no}.data": "zxcvbnm"}}
)
You can $unwind with includeArrayIndex option. Use the index to perform conditional update and $merge back into the collection.
db.collection.aggregate([
{
$match: {
unique_id: 1234
}
},
{
"$unwind": {
path: "$configs",
includeArrayIndex: "idx"
}
},
{
$set: {
"configs.data": {
"$cond": {
"if": {
$eq: [
"$config_no",
"$idx"
]
},
"then": "zxcvbnm",
"else": "$configs.data"
}
}
}
},
{
$group: {
_id: "$_id",
config_no: {
$first: "$config_no"
},
configs: {
$push: "$configs"
},
unique_id: {
$first: "$unique_id"
}
}
},
{
"$merge": {
"into": "collection",
"on": "_id",
"whenMatched": "merge"
}
}
])
Mongo Playground
I wrote
def user(lat, lon, distance, start_time, end_time):
param = {
"query": {
"filter": {
"geo_distance": {
"distance": distance,
"distance_type": "plane",
"location": {
"lat": lat,
"lon": lon
}
}
},
"query": {
"bool": {
"must": [
{"match": {"start_time": start_time}},
{"match": {"end_time": end_time}}
]
}
}
}
}
num = 0
results = get_data().query(param)
But TransportError(400, 'parsing_exception', 'no [query] registered for [filter]') error happens.I think the way of writing format of Elasticsearch is wrong.I used as reference,https://www.elastic.co/guide/en/elasticsearch/reference/5.2/query-dsl-geo-distance-query.html .But I cannot find the wrong point.How should I fix this?What is wrong in my code?
Your query needs to be like this:
param = {
"query": {
"bool": {
"filter": {
"geo_distance": {
"distance": distance,
"distance_type": "plane",
"location": {
"lat": lat,
"lon": lon
}
}
},
"must": [
{
"match": {
"start_time": start_time
}
},
{
"match": {
"end_time": end_time
}
}
]
}
}
}
I have documents in ES (Tweepy JSON) like this
{
"_source": {
"id": 792477813014224900,
"metadata": {
"iso_language_code": "en",
"result_type": "recent"
},
"retweeted": false,
"retweet_count": 330,
"user": {
"id": 149250899,
"listed_count": 0,
"protected": false,
"followers_count": 347,
"entities": {
"description": {
"urls": []
}
},
"screen_name": "Zwido_"
}
And I would like to search and query one full document based by user_name field.
I tryied this code
{
"nested": {
"path": "_source",
"score_mode": "avg",
"query": {
"bool": {
"must": [
{
"text": {"_source.user.user_name": user}
}
]
}
}
}
}
But it doesn't work and I received error
TransportError(400, 'search_phase_execution_exception', 'failed to parse search source. unknown search element [nested]
What I am doing wrong?
Thanks for help.
You don't need to specify the _source field + you're missing a query at the top-level, do it like this instead.
{
"query": {
"nested": {
"path": "user",
"score_mode": "avg",
"query": {
"bool": {
"must": [
{
"match": {"user.screen_name": user}
}
]
}
}
}
}
}
UPDATE
If your user field is not of nested type, then you can simply do it like this:
{
"query": {
"bool": {
"must": [
{
"match": {
"user.screen_name": user
}
}
]
}
}
}
as mentioned in the elasticsearch documentation here you should change the mapping of your data to tell elasticsearch that it is nested object. Once that is done then you can query the object.
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"
}
I am using elasticsearch where the query is to be posted in json and should be in standard order or else the result will be wrong. the problem is that the python is changing my json ordering. my original json query is.
x= {
"query": {
"filtered": {
"query": {
"query_string": {
"query": "*a*"
}
},
"filter": {
"and": {
"filters": [
{
"term": {
"city": "london"
}
},
{
"term": {
"industry.industry_not_analyed": "oil"
}
}
]
}
}
}
},
"facets": {
"industry": {
"terms": {
"field": "industry.industry_not_analyed"
}
},
"city": {
"terms": {
"field": "city.city_not_analyzed"
}
}
}
}
but the resulting python object is as follow.
{
'query': {
'filtered': {
'filter': {
'and': {
'filters': [
{
'term': {
'city': 'london'
}
},
{
'term': {
'industry.industry_not_analyed': 'oil'
}
}
]
}
},
'query': {
'query_string': {
'query': '*a*'
}
}
}
},
'facets': {
'city': {
'terms': {
'field': 'city.city_not_analyzed'
}
},
'industry': {
'terms': {
'field': 'industry.industry_not_analyed'
}
}
}
}
the result is different than what I need how do I solve this.
Use OrderedDict() instead of {}. Note that you can't simply use OrderedDict(query=...) because that would create an unordered dict in the background. Use this code instead:
x = OrderedDict()
x['query'] = OrderedDict()
...
I suggest to implement a builder for this:
x = Query().filtered().query_string("*a*").and()....