we use elasticsearch to power our classified search engine Listings360 Kenya.
In Elasticsearch version 6 during the search we could get the total hits documents count used for pagination here from this json output
Array
(
[took] => 3
[timed_out] =>
[_shards] => Array
(
[total] => 5
[successful] => 5
[skipped] => 0
[failed] => 0
)
[hits] => Array
(
[total] => 30540
[max_score] =>
[hits] => Array
(
[0] => Array
(
Now the exact same search with elasticsearch 7 give the following json output
Array
(
[took] => 14
[timed_out] =>
[_shards] => Array
(
[total] => 1
[successful] => 1
[skipped] => 0
[failed] => 0
)
[hits] => Array
(
[total] => Array
(
[value] => 10000
[relation] => gte
)
[max_score] =>
[hits] => Array
(
[0] => Array
(
You can see that i don't have the [hits][total] anymore which is used for pagination purpose.
Any idea how to get that back
Thank you for your help
jap, that´s one of the breaking changes in 7.0.
Have a look at the search param track_total_hits which forces the count to always be accurate. Nevertheless, the new format will still apply and you need to patch your application (that's why it's a breaking change).
Here is more detailed info regarding the new response structure.
Related
I have 2 dropdowns were content of the second one depends on the first one. I produce it's content by generating an array and passing it to JsonResponse
new JsonResponse($response_object);
My $response_object is created based on the list in the database where array keys match entity ID:
6 => 'A Item',
3 => 'B Item',
1 => 'C Item',
10 => 'D Item'
Problem is, that even tho I'm passing that list to JsonResponse as displayed (sorted by value), it displays it in the dropdown ordered by the key, not value.
This is how I build the response_object
foreach ($entities as $entity) {
$response_object->entities[$entity->getId()] = $entity->getName()
}
$response = new JsonResponse($response_object);
return $response;
Twig is a simple for widget
{{ form_widget(select_current_form.entity) }
Config in form builder for this particular field is
->add('entity', 'choice', array('required' => false, 'choices' => $entity_choices))
How to force it to display the list in order by value?
You can maybe try to use string as key in your array. Remember that you can use natsort to easily sort your array.
Instead of passing an array to the JsonResponse, if you pass an object you will be able to preserve its sorting.
Instead of this,
6 => 'A Item',
3 => 'B Item',
1 => 'C Item',
10 => 'D Item'
Arrange your function to bring an array of objects like this. (In PDO, you can use \PDO::FETCH_OBJ fetch mode)
[0] => stdClass Object
(
[id] => 6
[value] => A Item
)
[1] => stdClass Object
(
[id] => 3
[value] => B Item
)
[2] => stdClass Object
(
[id] => 1
[value] => C Item
)
[3] => stdClass Object
(
[id] => 10
[value] => D Item
)
I hope someone will find this helpful.
I'm using CakePHP 2.5.2 and having a bit of trouble searching for data efficiently.
In my application I've 3 tables, teams, players, skills... In teams there are 80 records, players 2400 records, skills 2400 records... I want to calculate the average skill of a team...
//Team model
public $actsAs = array('Containable');
public $hasMany = array('Player');
//Player model
public $actsAs = array('Containable');
public $hasOne = array('Skill');
public $belongsTo = array('Team');
//Skill model
public $actsAs = array('Containable');
public $belongsTo = array('Player');
My research is:
$team = $this->Team->find('all', array(
'contain' => array(
'Player' => array(
'Skill'
)
),
));
$this->set('team', $team);
that gives the expected result:
Array
(
[0] => Array
(
[Team] => Array
(
[id] => 1
[name] => my_team_name
)
[Player] => Array
(
[0] => Array
(
[id] => 000000419
[name] => Name
[surname] => Surname
[age] => 21
[team_id] => 1
[Team_id] => 1
[Skill] => Array
(
[id] => 20
[player_id] => 000000419
[skill] => 599
)
), ecc.....
This structure use at least 1680 queries... that are too much for me...
I've tried an other way, that involve just one query, returns a bad data structure but all the information that i need (also redundant). unfortunately follow this way i can not iterate in View to display what i need.
$player = $this->Team->Player->find('all', array(
'contains' => array(
'Skill',
),
that returns
Array
(
[0] => Array
(
[Player] => Array
(
[id] => 000000400
[nome] => my_player_name
[cognome] => my_player_surname
[nation_id] => 380
[age] => 29
[team_id] => 2
)
[Team] => Array
(
[id] => 2
[nome] => my_team_name
)
[Skill] => Array
(
[id] => 1
[player_id] => 000000400
[average] => 632
)
)
ecc.
Is there a way to iterate in VIEV to get the average skill of every team? Any other solutions?
Thanks!
You can use my plugin to solve this issue if you can upgrade CakePHP to 2.6 or later. The plugin has a high compatibility with ContainableBehavior, but generates better queries.
I think that the find operation will execute only 2 queries then.
I would be happy if you try it.
https://github.com/chinpei215/cakephp-eager-loader
Usage
1. Enable EagerLoader plugin
// In your model
$actsAs = ['EagerLoader.EagerLoader'];
If you are afraid that loading my plugin breaks something somewhere, you can also enable it on the fly.
// On the fly
$this->Team->Behaviors->load('EagerLoader.EagerLoader');
2. Execute the same find operation
$this->Team->find('all', ['contain' => ['Player' => ['Skill']]]);
3. See the query log
You will see the query log such as the following:
SELECT ... FROM teams AS Team WHERE 1 = 1;
SELECT ... FROM players AS Player LEFT JOIN skills AS Skill ON Player.id = Skill.player_id WHERE Player.id IN ( ... );
if you feeling that query searching so many tables (ie, models) then
you can unbind those model, before performing search with find()
if you want to fetch some particular column of a table, then remove
others column by selecting "fields" in find().
I have the following query in a Cakephp 2.4 model:
$scores = $this->WorkInfo->find('list', array(
'conditions' => array('WorkInfo.work_id' => $work_ids),
'fields' => array('WorkInfo.date', 'SUM(WorkInfo.score)'),
'group' => array('WorkInfo.date')
));
Which generates the following query:
SELECT
`WorkInfo`.`date`,
SUM(`WorkInfo`.`score`)
FROM
`home`.`work_infos` AS `WorkInfo`
WHERE
`WorkInfo`.`work_id` IN (4, 7, 8, 12, 9, 11, 13, 10, 14, 6, 5)
GROUP BY
`WorkInfo`.`date`
The result I get in my application is:
'2014-03-24' => null
'2014-03-25' => null
'2014-03-26' => null
'2014-03-27' => null
'2014-03-28' => null
'2014-03-31' => null
While the result I get from pasting this very query in the mysql console is:
'2014-03-24' => 0
'2014-03-25' => 36
'2014-03-26' => 0
'2014-03-27' => 164
'2014-03-28' => 0
'2014-03-31' => 0
What is going on here? It is supposed that same queries output same results, isn't it?
I have read something about creating virtual fields for this, but I do not want to overkill, it should be possible to perform a simple aggregation query through Cakephp using the find function.
Thanks!
Try this
$scores = $this->WorkInfo->find('all', array(
'conditions' => array('work_id' => $work_ids),
'fields' => array('date', 'SUM(score) AS score'),
'group' => array('date')
));
then with Set::combine you can format your array cakephp find list
$scores = Set::combine($scores, '{n}.WorkInfo.date', '{n}.0.score');
prints=>
'2014-03-24' => 0
'2014-03-25' => 36
'2014-03-26' => 0
'2014-03-27' => 164
'2014-03-28' => 0
'2014-03-31' => 0
Ok, sadly, I think what you want to do can't be done as you want to do it.
Let's see, you use the find('list') method, so that's here in the API. Code looks normal, and as you said, query is ok, returns everything you want. Problem is in line 2883
return Hash::combine($results, $query['list']['keyPath'], $query['list']['valuePath'], $query['list']['groupPath']);
That line organizes the returned array after the query is done. And seeing the doc for that function, we have
Creates an associative array using a $keyPath as the path to build its
keys, and optionally $valuePath as path to get the values. If
$valuePath is not specified, or doesn’t match anything, values will be
initialized to null.
Which is what happens to you. Now, debugging, the query result before applying the Hash::combine function is something like this
Array
(
[0] => Array
(
[WorkInfo] => Array
(
[date] => 2013-04-01
)
[0] => Array
(
[SUM(`WorkInfo`.`score`)] => 24
)
)
)
so you see, you get the results. And the respective Hash::combine
Array
(
[groupPath] =>
[valuePath] => {n}.SUM(WorkInfo.score)
[keyPath] => {n}.WorkInfo.date
)
which probably causes problem with the dot inside the parenthesis. And the combine function doesn't find the valuePath, and you get null, and you get sad.
If you change your query to 'SUM(WorkInfo.score) AS score' (leaving everything as is), you have almost the same problem with valuePath
Array
(
[groupPath] =>
[valuePath] => {n}.SUM(WorkInfo.score) as score
[keyPath] => {n}.WorkInfo.date
)
//respective result array
Array
(
[0] => Array
(
[WorkInfo] => Array
(
[date] => 2013-04-01
)
[0] => Array
(
[score] => 24
)
)
)
You might think that doing 'SUM(score) AS score' (without the dot) will solve it, but the code of find('list') adds the alias if it doesn't find a dot (in line 2865).
So... I guess what I'm saying is: do a virtual field, or listen to Isaac Rajaei, or create a custom find function. But with find('list') and SUM() you won't have luck :(
I need to build WP_Query that will return data from database where both conditions are fulfilled, because of that I'm using AND as relation but returned data are different than I expected. To make it more clear I will post WP_Query arguments here.
Array(
[post_type] => Array
(
[0] => event
)
[post_status] => publish
[paged] => 1
[posts_per_page] => 1000
[tax_query] => Array
(
[relation] => AND
[1] => Array
(
[taxonomy] => event_dates
[field] => slug
[terms] => Array
(
[0] => thursday
[1] => exhibitions
)
)
)
)
With this arguments I thought that I'll get events with type exibition AND are on Thursday.
Thanks in advance for help.
The AND is on the wrong level. The WP_Query arguments should look like something like this:
...
'tax_query' => array(
array(
'taxonomy' => 'event_dates',
'field' => 'slug',
'terms' => array('thursday', 'exhibitions'),
'operator' => 'AND'
)
)
...
$categ = $this->FreeadsCategory->bindModel( array( 'hasMany' => array( 'Subcategory' => array('foreignKey' => 'category_id', 'order'=>'id ASC') ) ) );
$data = $this->FreeadsCategory->findById($i);
$this->set("datas", $data);
I am not able to fetch the datas in view page using cakephp
If i give pr($datas); showing nothing in ctp file
If i print the data in controller i am getting the following array structure
Array
(
[FreeadsCategory] => Array
(
[id] => 1
[uuid] => 51512434-e4c4-441b-b90e-16f8732d5573
[category] => Automobiles
[status] => Active
)
[Subcategory] => Array
(
[0] => Array
(
[id] => 1
[uuid] => 4ea15f22-adf0-4020-b35d1-052ff9ff9a27
[category_id] => 1
[subcategory] => Cars/Cabs/Jeeps
[status] => Active
)
[1] => Array
(
[id] => 5
[uuid] => 51cec363-e7ac-4095-a86b-0ccdf260d1b4
[category_id] => 1
[subcategory] => Buses/Lorries
[status] => Active
)
)
You don't fetch data in views, that violates the MVC pattern. Technically there are ways to do it but it's plain wrong, you'll end up with unmaintanable garbage code.
I really recommend you to get started by reading about the MVC design pattern and to do the CakePHP blog tutorial first to get a minimum of understanding of how CakePHP works.