I want to sort results on the release date. I want 2015 movies first and the rest of the years sorted on the has_poster value. So I get results like:
2015, 2015, 1989, 2017, 2006
etc.
So far this is what I've got.
$params['index'] = 'movies';
$params['type'] = 'movie';
$params['body']['size'] = 50;
$params['body']['sort'] = array(
array('has_poster' => "desc"),
array('_score' => "desc"),
);
$params['body']['query']['filtered'] = array(
'query' => array(
'query_string' => array(
'query' => "survivor",
'fields' => array('name', 'orig_title'),
'default_operator' => "AND"
),
)
);
I need the equivalent of ... ORDER BY FIELD(releasedate, 2015), has_poster DESC ... in MySQL for Elasticsearch.
You need a scripted sorting:
{
"sort": [
{
"_script": {
"script": "if(doc['releasedate'].date.year==2015) return 1; else return 0;",
"type": "number",
"order": "desc"
}
},
{
"has_poster": "desc"
}
]
}
Im not work =>type name is string
$params['body']['sort']= array('name' => 'desc' );
or
$params=[
'index'=>'pets',
'type'=>'bird',
'body'=>[
'query'=>[
'bool'=>[
'must'=>[],
'filter'=>[
'range'=>[
'registered'=>[
'gte' => "2020-10-01",
'lte' => "2020-11-30"]
]
]
]
],
'sort'=>[
'name'=>[
'order'=>'asc'
]
]
]
];
but not work
Related
Appreciate your time!
After reviewing several 'Compare and Merge' threads, finally, I am going to request someone to help with this very specific scenario.
$input = array(
[ 2616 ] => array(
[ 9878767654 ] => array(
[ 987987987 ] => 987987987,
[ 987987986 ] => 987987986,
),
),
[ 2618 ] => array(
[ 9878767654 ] => array(
[ 987987987 ] => 987987987,
),
),
[ 'tmp-9878767654' ] => array(
[ 9878767654 ] => array(
[ 987987985 ] => 987987985,
[ 987987987 ] => 987987987,
),
),
[ 'tmp-9878767655' ] => array(
[ 9878767655 ] => array(
[ 987987975 ] => 987987975,
),
),
);
$desired_output = array(
[ 2616 ] => array(
[ 9878767654 ] => array(
[ 987987987 ] => 987987987,
[ 987987986 ] => 987987986,
[ 987987985 ] => 987987985,
),
),
[ 2618 ] => array(
[ 9878767654 ] => array(
[ 987987987 ] => 987987987,
[ 987987986 ] => 987987986,
[ 987987985 ] => 987987985,
),
),
[ 'tmp-9878767655' ] => array(
[ 9878767655 ] => array(
[ 987987975 ] => 987987975,
),
),
);
This is the inventory of products (listed by Product ID and Model ID) by Store ID. I want to merge the Model ID values WHERE the product id is the same FROM the array with store-ID starting with 'tmp-'. If product ID is not matched then I want that array to stay as it is. I hope I am making some sense.
Please help.
Here is a snippet to solve the specific problem posed by your example:
$temporaryStores = [];
$prefix = 'tmp-';
$prefixLength = strlen($prefix);
// extract the temporary store structures
foreach ($input as $storeId => $store) {
if (is_string($storeId) && strpos($storeId, $prefix) === 0) {
$productId = (int) substr($storeId, $prefixLength);
$temporaryStores[$productId] = $store;
unset($input[$storeId]);
}
}
// merge matching temporary store structures into the actual ones
$mergedProductIds = [];
foreach ($temporaryStores as $temporaryProductId => $temporaryModels) {
$temporaryModels = reset($temporaryModels); // Incompatible array structure
foreach ($input as $storeId => $store) {
foreach ($store as $productId => $models) {
if ($productId === $temporaryProductId) {
$modelsIds = array_merge($temporaryModels, $models);
$modelsIds = array_unique($modelsIds);
$input[$storeId][$productId] = $modelsIds;
$mergedProductIds[] = $temporaryProductId;
unset($temporaryStores[$temporaryProductId]);
}
}
}
}
// append leftover temporary store structures to the result
foreach ($temporaryStores as $temporaryProductId => $temporaryModels) {
if (!in_array($temporaryProductId, $mergedProductIds, true)) {
$input[$prefix . $temporaryProductId] = $temporaryModels;
}
}
var_dump($input);
This snippet might work for you or not. Either way, I strongly suggest you refactor this code into using a more object oriented design. Where it is made obvious what each value/structure represents, and validation can occur in isolation.
Now you are left having to deal with incompatible array structures that visually look like an incomprehensible mess.
I have an application that retrieves data from a mysql database and generates a json output with php to send to a plugin.
I'm generating the following json output from php:
{
"mapwidth":"1300",
"mapheight":"1000",
"categories":"[]",
"levels":{
"id":"lots",
"title":"Lots",
"map":"maps\/lot-map.svg",
"minimap":"",
"locations":[
{
"id":"lot1",
"title":"Lot 1",
"pin":"hidden",
"description":"<p>Status: <b style=\\\"color: #8eba5e;\\\">Available<\/b><br>Size:\u00a0<b>850 sqm<\/b><br>Please get in touch for an Offer.<\/p>",
"link":null,
"x":"0.4849",
"y":"0.4629",
"fill":null,
"category":"false",
"action":"tooltip"
}
]
},
"maxscale":"1.8"
}
But the format is incorrect. Should be like the following tested json file:
{
"mapwidth": "1300",
"mapheight": "1000",
"categories": [],
"levels": [
{
"id": "lots",
"title": "Lots",
"map": "maps/lot-map.svg",
"minimap": "",
"locations": [
{
"id": "lot12",
"title": "Lot 12",
"pin": "hidden",
"description": "<p>Status: <b style=\"color: #8eba5e;\">Available</b><br>Size: <b>850 sqm</b><br>Please get in touch for an Offer.</p>",
"link": "#more",
"x": "0.3726",
"y": "0.4565"
}
]
}
],
"maxscale": 1.8
}
The difference is in the "levels" key.
This is my php code:
$results = array(
'mapwidth' => '1300',
'mapheight' => '1000',
'categories' => '[]'
);
$results['levels'] = array(
'id' => 'lots',
'title' => 'Lots',
'map' => 'maps/lot-map.svg',
'minimap' => ''
);
if ($lotes)
{
// build usable array
foreach($lotes['results'] as $lote)
{
$results['levels']['locations'][] = array(
'id' => $lote['slug'],
'title' => $lote['title'],
'pin' => $lote['pin'],
'description' => $lote['description'],
'link' => $lote['link'],
'x' => $lote['position_x'],
'y' => $lote['position_y'],
'fill' => $lote['fill'],
'category' => $lote['category'],
'action' => $lote['action']
);
}
}
else
$results['error'] = lang('core error no_results');
$results['maxscale'] = '1.8';
// display results using the JSON formatter helper
display_json($results);
Any suggestions? Thanks
You need to make the levels a multidimensional array.
$results['levels'] = array();
$results['levels'][0] = array(
'id' => 'lots',
'title' => 'Lots',
'map' => 'maps/lot-map.svg',
'minimap' => ''
);
Then when you append to do, do it as follows:
$results['levels'][0]['locations'][] = array(
I wrote a mongodb query that I am having a hard time converting to php code:
var geoips = db.geoip.find().map(function(like){ return like.ip; });
var result = db.audit.aggregate([
{ $match: { ip: { $nin: geoips } } },
{ $group: {
_id: "$ip",
count: { $sum: 1 }
}}
]);
UPDATE:
The above query is the equivalent of the following Relation Database Query
Select ip,count(*)
from audit
where ip not in (select ip from geoip)
group by ip
Since I had to make this query in mongodb version 3.0, I was unable to take advantage of $lookup as suggested in an answer.
The below PHP code accomplishes the above objective and works as expected. It gets the distinct ips from geoip collection. It passes that result and does an aggregate on the audit collection to get the desired result.
$geoipcolln = $this->dbConn->selectCollection('geoip');
$geoips = $geoipcolln->distinct('ip');
$match = array('ip' => array('$nin' => $geoips));
$result = $this->collection->aggregate(
array(
'$match' => $match
),
array('$group' => array(
'_id' => '$ip',
'count' => array('$sum' => 1.0),
))
);
This can be done in one aggregation query using the $lookup operator as follows:
var result = db.audit.aggregate([
{
"$lookup": {
"from": "geoip",
"localField": "ip",
"foreignField": "ip",
"as": "geoips"
}
},
{ "$match": { "geoips.0": { "$exists": false } } },
{ "$group": {
"_id": "$ip",
"count": { "$sum": 1 }
}}
])
which can then be translated to PHP as:
<?php
$m = new MongoClient("localhost");
$c = $m->selectDB("yourDB")->selectCollection("audit");
$ops = array(
array(
"$lookup" => array(
"from" => "geoip",
"localField" => "ip",
"foreignField" => "ip",
"as" => "geoips"
)
),
array( "$match" => array( "geoips.0" => array( "$exists" => false ) ) ),
array( "$group" => array(
"_id" => "$ip",
"count" => array( "$sum" => 1 )
))
);
$results = $c->aggregate($ops);
var_dump($results);
?>
I need to "reformat" some data coming from an external API so it works with the nested list module of Sencha touch. I cannot change the data output of that external API. Here's an example of the data I get from the API:
$quest = array(
'gastronomy' => [
'restaurants' => [
'italians' => [
[
'title' => 'Al Castello',
'leaf' => true
],
[
'title' => 'Italia',
'leaf' => true
]
],
'asians' => [
[
'title' => 'Gautam',
'leaf' => true
],
[
'title' => 'Wok',
'leaf' => true
]
]
]
]
);
In order to make it work with sencha touch the data must look like this after "reformatting" it with a PHP Service:
$result = array(
'items' => [
[
'title' => 'gastronomy',
'items' => [
[
'title' => 'restaurants',
'items' => [
[
'title' => 'italians',
'items' => [
[
'title' => 'Al Castello',
'leaf' => true
],
[
'title' => 'Italia',
'leaf' => true
]
]
],
[
'title' => 'asians',
'items' => [
[
'title' => 'Gautam',
'leaf' => true
],
[
'title' => 'Wok',
'leaf' => true
]
]
]
]
]
]
]
]
);
I have tried every way I could think of but with no success. What really bugs me is that all keys must be renamed to items. (It's hard for me to access the deeper nested items because of that when I'm using a recursive function)
Haven't tested it, but it seems like a fairly simple recursive function should handle it.
For example:
function parseApi($arr) {
$result = array();
foreach ($arr as $key => $value) {
if (isset($value['leaf'])) {
$result[] = $value;
} else {
$result[] = array(
'title' => $key,
'items' => parseApi($value)
);
}
}
return $result;
}
$result = array( 'items' => $parseApi($quest);
You need a recursive function, and it needs to be able to tell the difference between associative and numerically-indexed arrays.
// from: http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
function isAssoc($arr) { return array_keys($arr) !== range(0, count($arr) - 1); }
function itemize($foo) {
$output = [];
if( ! isAssoc($foo) ) {
foreach( $foo as $value ) {
if( is_array($value) ) {
$output[] = itemize($value);
} else {
$output[] = $value;
}
}
} else {
foreach( $foo as $key => $value ) {
if( is_array($value) ) {
$output[] = [
'title' => $key,
'items' => itemize($value)
];
} else {
$output[$key] = $value;
}
}
}
return $output;
}
echo json_encode(itemize($quest), JSON_PRETTY_PRINT);
Output:
[
{
"title": "gastronomy",
"items": [
{
"title": "restaurants",
"items": [
{
"title": "italians",
"items": [
{
"title": "Al Castello",
"leaf": true
},
{
"title": "Italia",
"leaf": true
}
]
},
{
"title": "asians",
"items": [
{
"title": "Gautam",
"leaf": true
},
{
"title": "Wok",
"leaf": true
}
]
}
]
}
]
}
]
I am using the following MongoDB query (and it's working with RoboMongo), returning an array with 30 elements, one for each day of the date range specified on $match element:
db.alcobaca.aggregate( [
{ $project:
{ time:1,
temp:1,
frio:
{
$cond:
[{ $lte: [ "$temp", 7.2 ] }, 0.25, 0 ]}}},
{
$match: {
time: {
$gte: new Date('11/01/2011'),
$lt: new Date('11/30/2011')
}
}
},
{
$group: {
_id: {
ord_date: {
day: {$dayOfMonth: "$time"},
month: {$month: "$time"},
year: {$year: "$time"}
}
},
horasFrio: { $sum: '$frio' }
}
},
{ $sort: { '_id.ord_date': 1} }
])
When I translate to PHP, working on the Laravel framework, after a successful connection to the database (I have already tested it with another, simpler query):
$c->aggregate (
[
['$project' =>
['time' => 1,
'temp' => 1,
'frio' =>
['$cond' =>
[['$lte' => ['$temp', 7.2]], 0.25, 0]]]],
['$match' => [
'time' => [
'$gte' => new DateTime('11/01/2011'),
'$lt' => new DateTime('11/03/2011')
]
]
],
[
'$group' => [
'_id' => [
'ord_date' => [
'day' => ['$dayOfMonth' => '$time'],
'month' => ['$month' => '$time'],
'year' => ['$year' => '$time']
]
],
'horasFrio' => ['$sum' => '$frio']
]
],
['$sort' => ['_id.ord_date' => 1]]
]
);
It returns an empty array. Am I missing some syntax issue?
Thank you