I have a query in ES:
POST <index>/_search
{
"_source":[
<list_of_fields_to_return>
],
"size":"6",
"from":"0",
"min_score": 10,
"query":{
"function_score":{
"functions":[
{
"field_value_factor":{
"field":"product.sales_count",
"missing":0,
"modifier":"log1p"
}
},
{
"field_value_factor":{
"field":"product.image_count",
"missing":0,
"modifier":"log1p"
}
},
{
"field_value_factor":{
"field":"featureCount",
"missing":0,
"modifier":"log1p"
}
},
{
"field_value_factor":{
"field":"<field>",
"missing":0,
"modifier":"none",
"factor":5
}
},
{
"field_value_factor":{
"field":"<field>",
"missing":0,
"modifier":"none",
"factor":3
}
},
{
"field_value_factor":{
"field":"<field>",
"missing":0,
"modifier":"none",
"factor":2
}
},
{
"field_value_factor":{
"field":"<field>",
"missing":0,
"modifier":"none",
"factor":2
}
},
{
"field_value_factor":{
"field":"<field>",
"missing":0,
"modifier":"none",
"factor":1
}
}
],
"score_mode":"sum",
"query":{
"bool":{
"filter":[
{
"term":{
"product.is_visible":true
}
}
],
"should":[
{
"query_string":{
"fields":[
<field>
],
"query":"ALV3002688-SET~1"
}
},
{
"query_string":{
"fields":[
"<field>"
],
"query":"ALV3002688-SET",
"boost":"2.0"
}
},
{
"query_string":{
"fields":[
"product.ref"
],
"query":"*ALV3002688-SET*", <---- PROBLEM WITH "-" sign
"boost": 10
}
}
]
}
}
}
},
"aggs":{
"by_categories":{
"terms":{
"field":"<field>"
}
}
}
}
If i strip the "-SET", it matches perfectly, can't wildcard search for "-"? For now, it just returns 0 matching documents. I could do something like, strip "-" and replace it with whitespace but then It gives me all documents for example "something\SET".
Also, If I remove the "*" sign it maches perfectly.
What am I missing?
Related
I have written elastic search query in static values, now i want to make as a dynamic like i have input fields, based on the input values i have to make my dynamic elastic search query. how can i do it? any one please update my answer.
INPUT
{
"userID" : "USER1",
"groupID" : "5b278f8856db693c457b4697",
"contentType " : "question",
"contentID" : "5",
"contentFlow": [
{
"contentId": "123",
"contentType": "topic"
},
{
"contentId": "456",
"contentType": "concept"
},
{
"contentId": "100",
"contentType": "sdl"
}
]
}
STATIC QUERY
{
"size":999,
"query":{
"bool":{
"must":[
{
"term":{
"userId":"USER1"
}
},
{
"term":{
"contentId":"5"
}
},
{
"bool":{
"must":[
{
"term":{
"contentPath.contentType":"topic"
}
},
{
"term":{
"contentPath.contentId":"123"
}
}
]
}
},
{
"bool":{
"must":[
{
"term":{
"contentPath.contentType":"concept"
}
},
{
"term":{
"contentPath.contentId":"456"
}
}
]
}
},
{
"bool":{
"must":[
{
"term":{
"contentPath.contentType":"sdl"
}
},
{
"term":{
"contentPath.contentId":"100"
}
}
]
}
}
]
}
}
}
I am new to learning elastic search, kindly help me out on this problem
I have the following array.
{
"flow":[
{
"tasks":[
{ "id":"1", "uid":"bryan" },
{ "id":"2", "uid":"eric" }
]
},
{
"tasks":[
{ "id":"1", "uid":"bryan" },
{ "id":"2", "uid":"eric" }
]
},
{
"tasks":[
{ "id":"1", "uid":"bryan" },
{ "id":"2", "uid":"eric" }
]
},
{
"tasks":[
{ "id":"1", "uid":"bryan" },
{ "id":"2", "uid":"eric" },
{ "id":"3", "uid":"eric" },
{ "id":"4", "uid":"bryan" }
]
}
]
}
Let's say I am eric. If I am eric, I am trying to move all items with the uid of eric to the front of the tasks array.
So that the array would end looking like this:
{
"flow":[
{
"tasks":[
{ "id":"2", "uid":"eric" },
{ "id":"1", "uid":"bryan" }
]
},
{
"tasks":[
{ "id":"2", "uid":"eric" },
{ "id":"1", "uid":"bryan" }
]
},
{
"tasks":[
{ "id":"2", "uid":"eric" },
{ "id":"1", "uid":"bryan" }
]
},
{
"tasks":[
{ "id":"2", "uid":"eric" },
{ "id":"3", "uid":"eric" },
{ "id":"1", "uid":"bryan" },
{ "id":"4", "uid":"bryan" }
]
}
]
}
I've attempted to make a function to do it, but for some reason it's not working the way I intended it to. Does anyone know what I'm doing wrong?
function reorder_flow($flow, $uid)
{
foreach($flow as &$step)
{
//step is the array with tasks
$tasks = $step['tasks'];
$new_tasks = array();
foreach($tasks as $key => $t)
{
if($t['uid'] == $uid)
{
$new_tasks = $new_tasks + $t;
unset($tasks[$key]);
}
}
$step['tasks'] = $new_tasks + $step['tasks'];
}
return $flow;
}
This is a traversal/sorting problem.
$json = <<<JSON
{
"flow":[
{
"tasks":[
{ "id":"1", "uid":"bryan" },
{ "id":"2", "uid":"eric" }
]
},
{
"tasks":[
{ "id":"1", "uid":"bryan" },
{ "id":"2", "uid":"eric" }
]
},
{
"tasks":[
{ "id":"1", "uid":"bryan" },
{ "id":"2", "uid":"eric" }
]
},
{
"tasks":[
{ "id":"1", "uid":"bryan" },
{ "id":"2", "uid":"eric" },
{ "id":"3", "uid":"eric" },
{ "id":"4", "uid":"bryan" }
]
}
]
}
JSON;
$flow = json_decode($json, true);
array_walk($flow['flow'], function(&$flowItem, $key){
usort($flowItem['tasks'], function($a, $b){
$aIsMatch = $a['uid'] === 'eric';
$bIsMatch = $b['uid'] === 'eric';
if ($aIsMatch && $bIsMatch) {
return 0;
}
if ($aIsMatch) {
return -1;
}
if ($bIsMatch) {
return 1;
}
// Fallback sorting criteria - you could use something else or just return 0
return strcasecmp($a['uid'], $b['uid']);
});
});
echo json_encode($flow, JSON_PRETTY_PRINT);
Please try this:
function sortByUID(&$array, $uid) {
array_walk ($array, function($obj) use($uid) {
uasort($obj->tasks, function($a, $b) use($uid) {
return $a->uid == $uid ? -1 : 1;
});
});
}
sortByUID($data->flow, 'eric');
Demo: https://3v4l.org/mOhDX
I hope this will help.
notes:
+ does not work with arrays in that way
json_decode should have the second parameter set to true to get nested arrays
then try this in the foreach:
//step is the array with tasks
$new_tasks=array();
foreach($step['tasks'] as $t){
if($t['uid'] == $uid){
array_unshift($new_tasks,$t);
} else {
array_push($new_tasks,$t);
}
}
$step['tasks'] = $new_tasks;
I am using a client for elasticsearch client for elasticsearch, i am not getting the right result for a multiple range query.
The body that i use for querying:
{
"index":"locations",
"type":"portugal",
"body":{
"aggs":{
"unique":{
"aggs":{
"documents":{
"top_hits":{
"size":50
}
}
},
"terms":{
"field":"cp3"
}
}
},
"query":{
"filtered":{
"filter":{
"bool":{
"must":{
"range":{
"latitude":{
"gte":41.1373667,
"lte":41.1373767
},
"longitude":{
"gte":-8.631723,
"lte":-8.631713
}
}
}
}
}
}
}
}
}
the result:
{
"took":2,
"timed_out":false,
"_shards":{
"total":5,
"successful":5,
"failed":0
},
"hits":{
"total":1,
"max_score":1,
"hits":[
{
"_index":"locations",
"_type":"portugal",
"_id":"AVTJ4I0g_vwSgXBDKO-W",
"_score":1,
"_source":{
"id":222956,
"latitude":41.0383217,
"longitude":-8.6317147
}
}
]
},
"aggregations":{
"unique":{
"doc_count_error_upper_bound":0,
"sum_other_doc_count":0,
"buckets":[
{
"key":199,
"doc_count":1,
"documents":{
"hits":{
"total":1,
"max_score":1,
"hits":[
{
"_index":"locations",
"_type":"portugal",
"_id":"AVTJ4I0g_vwSgXBDKO-W",
"_score":1,
"_source":{
"id":222956,
"latitude":41.0383217,
"longitude":-8.6317147
}
}
]
}
}
}
]
}
}
}
as you can see the result's latitude is not inside the latitude range i gave it.
Using the Head plugin from elasticsearch to test:
my query:
{
"query":{
"bool":{
"must":[
{
"range":{
"latitude":{
"gte":"41.1363671",
"lte":"41.1363771"
}
}
},
{
"range":{
"longitude":{
"gt":"-8.6318828",
"lte":"-8.6318728"
}
}
}
],
"must_not":[
],
"should":[
]
}
},
"from":0,
"size":10,
"sort":[
],
"aggs":{
}
}
The result:
(empty), there is no records in this range.
Edit:
added the mapping for my index:
{
"locations":{
"aliases":{
},
"mappings":{
"portugal":{
"properties":{
"cp3":{
"type":"long"
},
"cp4":{
"type":"long"
},
"cpalf":{
"type":"string"
},
"id":{
"type":"long"
},
"latitude":{
"type":"double"
},
"localidade":{
"type":"string"
},
"longitude":{
"type":"double"
}
}
}
},
"settings":{
"index":{
"creation_date":"1463675755006",
"number_of_shards":"5",
"number_of_replicas":"1",
"uuid":"C9OO0ig_QyeigqSufK8_dA",
"version":{
"created":"2030199"
}
}
},
"warmers":{
}
}
}
Test with the following query :
{
"query":{
"bool":{
"must":[
{
"range":{
"latitude":{
"gte": 41.1363671,
"lte": 41.1363771
}
}
},
{
"range":{
"longitude":{
"gt": -8.6318828,
"lte": -8.6318728
}
}
}
],
"must_not":[
],
"should":[
]
}
},
"from":0,
"size":10,
"sort":[
],
"aggs":{
}
}
As longitude and latitude fields are double type the should be compare with double, but you have compared with string.
I have setup snowplow with Elasticsearch.
When I want to get the data out I just do normal queries and use aggregates to get them by day, country etc.
So I want to figure out clickthru rate for these aggregations, I have 2 kind of events: page views and clicks.
Currently I do 2 queries:
Page Views:
{
"size": 0,
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"term": {
"event": "page_view"
}
}
],
"must_not": {
"term": {
"br_family": "Robot"
}
}
}
}
}
},
"aggs": {
"dates": {
"date_histogram": {
"field": "collector_tstamp",
"interval": "day"
}
}
}
}
Clicks:
{
"size": 0,
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"term": {
"event": "struct"
}
},
{
"term": {
"se_action": "click"
}
}
],
"must_not": {
"term": {
"br_family": "Robot"
}
}
}
}
}
},
"aggs": {
"dates": {
"date_histogram": {
"field": "collector_tstamp",
"interval": "day"
}
}
}
}
I format the response to something easier to use and then merge them in PHP using something like this.
function merge_metrics($pv,$c){
$r = array();
if(count($pv) > 0){
foreach ($pv as $key => $value) {
$r[$value['name']]['page_views'] += $value['count'];
}
}
if(count($c) > 0){
foreach ($c as $key => $value) {
$r[$value['name']]['clicks'] += $value['count'];
}
}
$rf = array();
foreach ($r as $key => $value) {
$tmp_clicks = isset($value['clicks']) ? $value['clicks'] : 0;
$tmp_page_views = isset($value['page_views']) ? isset($value['page_views']) : 0;
$rf[] = array(
'name' => $key,
'page_views' => $tmp_page_views,
'clicks' => $tmp_clicks,
'ctr' => ctr($tmp_clicks,$tmp_page_views)
);
}
return $rf;
}
Both $pv and $c are arrays that contain the aggregates that result from querying Elasticsearch and I do some formatting for ease of use.
My question is:
Is it possible get multiple metrics(in my case page views and clicks, these are specific filters) and perform same aggregations on both ? then returning the aggregations something like :
{
"data": [
{
"day": "2015-10-13",
"page_views": 61,
"clicks": 0,
},
{
"day": "2015-10-14",
"page_views": 135,
"clicks": 1,
},
{
"day": "2015-10-15",
"page_views": 39,
"clicks": 0,
}
]
}
But without me having to manually merge them ?
Yes, it is definitely possible if you merge your aggregations into one single query. For instance, I suppose you have one query like this for page views:
{
"query": {...}
"aggregations": {
"by_day": {
"date_histogram": {
"field": "day",
"interval": "day"
},
"aggs": {
"page_views_per_day": {
"sum": {
"field": "page_views"
}
}
}
}
}
}
And another query like this for clicks:
{
"query": {...}
"aggregations": {
"by_day": {
"date_histogram": {
"field": "day",
"interval": "day"
},
"aggs": {
"clicks_per_day": {
"sum": {
"field": "clicks"
}
}
}
}
}
}
Provided you have the same constraints in your query, you can definitely merge them together at the date_histogram level, like this:
{
"query": {...}
"aggregations": {
"by_day": {
"date_histogram": {
"field": "day",
"interval": "day"
},
"aggs": {
"page_views_per_day": {
"sum": {
"field": "page_views"
}
},
"clicks_per_day": {
"sum": {
"field": "clicks"
}
}
}
}
}
}
UPDATE
Since your queries are different for each of your aggregations, we need to do it slightly differently, i.e. by using an additional filters aggregation, like this:
{
"size": 0,
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"terms": {
"event": [
"page_view",
"struct"
]
}
}
],
"should": {
"term": {
"se_action": "click"
}
},
"must_not": {
"term": {
"br_family": "Robot"
}
}
}
}
}
},
"aggs": {
"dates": {
"date_histogram": {
"field": "collector_tstamp",
"interval": "day"
},
"aggs": {
"my_filters": {
"filters": {
"filters": {
"page_views_filter": {
"bool": {
"must": [
{
"term": {
"event": "page_view"
}
}
],
"must_not": {
"term": {
"br_family": "Robot"
}
}
}
},
"clicks_filter": {
"bool": {
"must": [
{
"term": {
"event": "struct"
}
},
{
"term": {
"se_action": "click"
}
}
],
"must_not": {
"term": {
"br_family": "Robot"
}
}
}
}
}
}
}
}
}
}
}
Now for each daily bucket, you're going to end up with two sub-buckets, one for the count of page views and another for the count of clicks.
This question already has an answer here:
How to extract and access data from JSON with PHP?
(1 answer)
Closed 7 years ago.
Any help? This has been driving me nuts!!! I have taken an xml file and dumped the namespaces and have a great array but for the life of me can't figure out how to work with the json to get variable for:
{
"ListMatchingProductsResponse": {
"ListMatchingProductsResult": {
"Products": {
"Product": [
{
"Identifiers": {
"MarketplaceASIN": {
"MarketplaceId": "ATVPDKIKX0DER",
"ASIN": "B000WTLJIQ"
}
},
"AttributeSets": [],
"Relationships": {
"VariationParent": {
"Identifiers": {
"MarketplaceASIN": {
"MarketplaceId": "ATVPDKIKX0DER",
"ASIN": "**B00FM1EXEQ**"
}
}
}
},
"SalesRankings": {
"SalesRank": [
{
"ProductCategoryId": "pet_products_display_on_website",
"Rank": "115236"
},
{
"ProductCategoryId": "**5769007011**",
"Rank": "362"
}
]
}
},
{
"Identifiers": {
"MarketplaceASIN": {
"MarketplaceId": "ATVPDKIKX0DER",
"ASIN": "B00NDY7666"
}
},
"AttributeSets": [],
"Relationships": [],
"SalesRankings": []
},
{
"Identifiers": {
"MarketplaceASIN": {
"MarketplaceId": "ATVPDKIKX0DER",
"ASIN": "B009YJ3JSI"
}
},
"AttributeSets": [],
"Relationships": {
"VariationParent": {
"Identifiers": {
"MarketplaceASIN": {
"MarketplaceId": "ATVPDKIKX0DER",
"ASIN": "B00P3MYXHQ"
}
}
}
},
"SalesRankings": {
"SalesRank": [
{
"ProductCategoryId": "pet_products_display_on_website",
"Rank": "180220"
},
{
"ProductCategoryId": "3203999011",
"Rank": "8108"
}
]
}
},
{
"Identifiers": {
"MarketplaceASIN": {
"MarketplaceId": "ATVPDKIKX0DER",
"ASIN": "B00ARCFLFA"
}
},
"AttributeSets": [],
"Relationships": [],
"SalesRankings": {
"SalesRank": [
{
"ProductCategoryId": "pet_products_display_on_website",
"Rank": "297848"
},
{
"ProductCategoryId": "5769009011",
"Rank": "879"
}
]
}
},
{
"Identifiers": {
"MarketplaceASIN": {
"MarketplaceId": "ATVPDKIKX0DER",
"ASIN": "B00DJAEX6U"
}
},
"AttributeSets": [],
"Relationships": {
"VariationParent": {
"Identifiers": {
"MarketplaceASIN": {
"MarketplaceId": "ATVPDKIKX0DER",
"ASIN": "B0091TK10K"
}
}
}
},
"SalesRankings": []
},
{
"Identifiers": {
"MarketplaceASIN": {
"MarketplaceId": "ATVPDKIKX0DER",
"ASIN": "B00FC7ALY6"
}
},
"AttributeSets": [],
"Relationships": [],
"SalesRankings": []
}
]
}
},
"ResponseMetadata": {
"RequestId": "9d9da767-ffc5-4eb3-ab95-8f9e91dc7af2"
}
}
}
use json_decode() and it will turn your json into an object.
$json = json_decode(<json_string));
Use json_decode() to return an array then use foreach loop
$result = json_decode($yourJSON);
foreach($result as $key => $val){
//do something here
echo 'Key: ' .$key . ' Value: ' . $val;
}