I'm having a problem with an Elastica QueryBuilder exact search in a Symfony app. The Elastica version is 2.1, which depends on Elasticsearch 1.5.2. I'm searching an index where one of the fields is mapped as
majors:
type: string
index : not_analyzed
The field is a student's major that can have one or more words, such as "Ancient History".
The query is set up like this:
/** #var ElasticaFactory $ef */
protected $ef;
public function __construct(ElasticaFactory $ef)
{
$this->ef = $ef;
}
$query = $this->ef->createQuery();
$qb = $this->ef->createQueryBuilder();
$bool = $qb->filter()->bool();
$query->setQuery(
$qb->query()->filtered(
$qb->query()->term(),
$bool->addShould(
$qb->filter()->term(
array('majors' => $params['majors'])
)
)
)
);
When I run this query, I get a SearchPhaseExecutionException error. The full text of the error message is here.
Stack trace shows the full contents of the request:
Client ->request ('students/_search', 'GET', array('query' => array('filtered' => array('query' => array('term' => array()), 'filter' => array('bool' => array('should' => array(array('term' => array('majors' => 'Ancient Studies')))))))), array('from' => '0', 'size' => '10'))
in /vagrant/persona/vendor/ruflin/elastica/lib/Elastica/Search.php at line 455
When I set up the query as a "match" below, it works with no errors:
$query->setQuery(
$qb->query()->filtered(
$qb->query()->match('majors', $params['majors']),
$bool
)
);
However, a match query returns too many irrelevant results. I need specifically an exact search query.
Next, in order to eliminate any issues with Elastica, I converted the query into a raw ES query, like this:
$query->setRawQuery(
array(
'query' => array(
'filtered' => array(
'query' => array(
'term' => array()),
'filter' => array(
'bool' => array(
'should' => array(
array(
'term' => array(
'majors' => 'Art History'
)
)
)
)
)
)
)
)
);
This gave me the same error message as quoted above. Looks like there is a problem with the query itself, and not with Elastica.
When I rearranged the query to exactly follow the documentation as below, it returned no results, even though matching records were present
$query->setRawQuery(
array(
'query' => array(
'filtered' => array(
'filter' => array(
'term' => array(
'majors' => 'Art History'
)
)
)
)
)
);
Any help would be appreciated!
Related
I'm using the code autogenerated by facebook to try and connect to the marketing API to get campaign stats. In doing so, I'm getting:
Uncaught FacebookAds\Http\Exception\AuthorizationException: (#100) results, actions:like, video_play_actions:video_view, video_avg_time_watched_actions:video_view, unique_actions:link_click are not valid for fields param.
$fields = array(
'results',
'reach',
'actions:like',
'video_play_actions:video_view',
'video_avg_time_watched_actions:video_view',
'unique_actions:link_click',
);
var_dump($fields);
$params = array(
'level' => 'campaign',
'filtering' => array(array('field' => 'campaign.delivery_info','operator' => 'IN','value' => array('active'))),
'breakdowns' => array(),
'time_range' => array('since' => '2017-05-19','until' => '2019-05-19'),
);
echo json_encode((new AdAccount($ad_account_id))->getInsights(
$fields,
$params
)->getResponse()->getContent(), JSON_PRETTY_PRINT);
Above I used campaign.delivery_info per this answer. I've also tried (per the auto-generated code):
'filtering' => array(array('field' => 'delivery_info','operator' => 'IN','value' => array('active')))
Seems you are asking for old values field, try this:
$fields = array(
'reach',
'actions',
'video_play_actions',
'video_avg_time_watched_actions',
'outbound_clicks',
);
Hope this help
NB: results field is not available
I am trying to find out the names between a time period.
But the problem is when i try to run it
first-- it returns the selected names value
second -- it returns data between that period.
Now what i want to do is that, i want to search name between a time period.
For explaining it more, suppose we have select a name "john", and select a date 2/08/2015 to 27/08/2015,
so it should return all the names between that time period.
But it is returning the names of john and than searching for other documents between that period, where is should also take the name "John" when searching the date !
How to solve this problem !
$name = $request->request->get('name');
$strat_date = $request->request->get('strat_date');
$end_date = $request->request->get('end_date');
$params = array(
'index' => "myIndex",
'type' => "myType",
'body' => array(
'query' => array(
'bool' => array(
'must' => array(
// empty should clause for starters
)
)
)
)
);
// add each constraint in turn depending on whether the param is specified
if (!empty($sourceFilter)) {
$params['body']['query']['bool']['must'] = array(
'query_string' => array(
'default_field' => 'name',
'query' => implode(" ", $name)
)
);
}
if (!empty($end_date)) {
$params['body']['query']['bool']['must']['range'] = array(
'datehistory' => array(
"from" => $strat_date,
"to" => $end_date
)
);
}
// special case if none is present, just match everything
if (count($params['body']['query']['bool']['must']) == 0) {
$params['body']['query'] = array(
'match_all' => array()
);
}
$docs = $client->search($params);
But at always return the an error like this ----
{"error":"SearchPhaseExecutionException[Failed to execute phase
[query], all shards failed; shardFailures
{[agEfJ6ltSJmlec3gpnPg3g][myIndex][1]:
SearchParseException[[myIndex][1]: from[-1],size[-1]: Parse Failure
[Failed to parse name
[{\"query\":{\"bool\":{\"must\":{\"query_string\":{\"default_field\":\"name\",\"query\":\"john.se\"},\"range\":{\"datehistory\":{\"from\":1438207200,\"to\":1440626400}}}}}}]]];
nested: QueryParsingException[[myIndex] No query registered for
[datehistory]]; }]","status":400}
You have a mix of bool/should and bool/must so you simply need to change bool/should to bool/must.
$params = array(
'index' => "myIndex",
'type' => "myType",
'body' => array(
'query' => array(
'bool' => array(
'must' => array( <--- CHANGE
// empty should clause for starters
)
)
)
)
);
// add each constraint in turn depending on whether the param is specified
if (!empty($sourceFilter)) {
$params['body']['query']['bool']['must'][] = array( <--- CHANGE
'query_string' => array(
'default_field' => 'name',
'query' => implode(" ", $name)
)
);
}
if (!empty($end_date)) {
$params['body']['query']['bool']['must'][] = array( <--- CHANGE
'range' => array(
'datehistory' => array(
"from" => $strat_date,
"to" => $end_date
)
)
);
}
// special case if none is present, just match everything
if (count($params['body']['query']['bool']['must']) == 0) { <-- CHANGE
$params['body']['query'] = array(
'match_all' => array()
);
}
$docs = $client->search($params);
i am trying to filter data based on the user selection.
as a example if a user select a name "Smith" and "Type(Which is male of female)", it actually works fine.
The problem is if a user do not select any name and just select just type, than based on the type to should query the data, which means it should select all "names", instead of selecting a single names.
Now if the user do not select any name it returns null value in the query, so how can i make the query to act like when nothing is "post" it should "select all".
Do any one knows any solution for this problem !
if ($request->getMethod() == 'POST') {
$name = $request->request->get('name'); // get requested name
$type = $request->request->get('type'); // Which is male of female
$params = array(
'index' => "myIndex",
'type' => "myType",
'body' => array(
'query' => array(
'bool' => array(
'should' => array(
'query_string' => array(
'default_field' => 'name',
'query' => $name
)
)
)
),
'term' => array(
"type" => $type
)
)
);
$docs = $client->search($params);
For making it more clear how to make a condition for elasticserch if post value is null select all
I think you should simply build your query conditionally, i.e. add each constraint only if the related parameter is present in the request. Besides, you also have another issue in your query, i.e. the term query is misplaced, it should be located inside the bool/should and not directly in the body. So here is how I'd do it:
if ($request->getMethod() == 'POST') {
$name = $request->request->get('name'); // get requested name
$type = $request->request->get('type'); // Which is male of female
// create the base skeleton of your query
$params = array(
'index' => "myIndex",
'type' => "myType",
'body' => array(
'query' => array(
'bool' => array(
'should' => array(
// empty should clause for starters
)
)
)
)
);
// add each constraint in turn depending on whether the param is specified
if (!empty($name)) {
$params['body']['query']['bool']['should'] = array(
'query_string' => array(
'default_field' => 'name',
'query' => $name
)
);
}
if (!empty($type)) {
$params['body']['query']['bool']['should'] = array(
'term' => array(
"type" => $type
)
);
}
// special case if none is present, just match everything
if (count($params['body']['query']['bool']['should']) == 0) {
$params['body']['query'] => array(
'match_all' => array()
);
}
$docs = $client->search($params);
When i am trying this aggregation query on a sample mongo database of 25 entries, It works. But when the same method is applied for entire mongodb of 317000 entries, it doesn't respond. Even it's not showing any kind of error.
What to do for such problems.
$mongo = new Mongo("localhost");
$collection = $mongo->selectCollection("sampledb","analytics");
$cursor = $collection->aggregate(
array(
array(
'$group' => array(
'_id' => array(
'os'=>'$feat_os',
'minprice'=>'$finder_input_1',
'max_price'=>'$finder_input_2',
'feat_quadcode'=>'$feat_quadcore'
),
'count' => array('$sum' => 1)
)
),
array('$out'=>"result")
)
);
It feels like I've tried everything so I now come to you.
I am trying to order my data but it isn't going so well, kinda new to Cake.
This is my code:
$this->set('threads', $this->paginate('Thread', array(
'Thread.hidden' => 0,
'Thread.forum_category_id' => $id,
'order' => array(
'Thread.created' => 'desc'
)
)));
It generates an SQL error and this is the last and interesting part:
AND `Thread`.`forum_category_id` = 12 AND order = ('desc') ORDER BY `Thread`.`created` ASC LIMIT 25
How can I fix this? The field created obviously exists in the database. :/
You need to pass in the conditions key when using multiple filters (i.e. order, limit...). If you just specify conditions, you can pass it as second parameter directly.
This should do it:
$this->set('threads', $this->paginate('Thread', array(
'conditions' => array(
'Thread.hidden' => 0,
'Thread.forum_category_id' => $id
),
'order' => array(
'Thread.created' => 'desc'
)
)));
or perhaps a little clearer:
$this->paginate['order'] = array('Thread.created' => 'desc');
$this->paginate['conditions'] = array('Thread.hidden' => 0, ...);
$this->paginate['limit'] = 10;
$this->set('threads', $this->paginate());
if you get an error, add public $paginate; to the top of your controller.
Try
$this->set('threads', $this->paginate('Thread', array(
'Thread.hidden' => 0,
'Thread.forum_category_id' => $id
),
array(
'Thread.created' => 'desc'
)
));
I'm not a Cake master, just a guess.
EDIT. Yes, thats right. Cake manual excerpt:
Control which fields used for ordering
...
$this->paginate('Post', array(), array('title', 'slug'));
So order is the third argument.
try
$all_threads = $this->Threads->find('all',
array(
'order' => 'Threads.created'
)
);
$saida = $this->paginate($all_threads,[
'conditions' => ['Threads.hidden' => 0]
]);
There are a few things to take note of in paginate with order. For Cake 3.x, you need :
1) Ensure you have included the fields in 'sortWhitelist'
$this->paginate = [
'sortWhitelist' => [
'hidden', 'forum_category_id',
],
];
2) for 'order', if you put it under $this->paginate, you will not be able to sort that field in the view. So it is better to put the 'order' in the query (sadly this wasn't stated in the docs)
$query = $this->Thread->find()
->where( ['Thread.hidden' => 0, 'Thread.forum_category_id' => $id, ] )
->order( ['Thread.created' => 'desc'] );
$this->set('threads', $this->paginate($query)