SQL to MongoDB? - php

I like to implement
"SELECT * FROM TABLE_NAME
WHERE
name like '$query_string' or
title like '%$query_string%' or
tags like '%$query_string%'"
to mongoDB, and I tried
$condition = array('$or' =>
array('writer'=> array('name'=>"$query_string"),
'title'=> new MongoRegex("/$query_string/"),
'tags' => new MongoRegex("/$query_string/") ));
and this does not work.
What is proper way to implement that SQL to mongoDB?

Here's how I construct a case-insensitive, "contains" term
$containsTerm = new MongoRegex(sprintf('/%s/i', preg_quote($term, '/')));
So your condition might look like
$condition = array('$or' => array(
'writer.name' => $term,
'title' => $containsTerm,
'tags' => $containsTerm
));
Apologies if the condition array is wrong, I typically use the Doctrine ODM

Related

Elastic search scoring is always 0

Any idea why ElasticSearch would always return a _score of 0 for all the search queries i do ?
Using Elastica, i am doing something like:
$elasticaClient= $this->getElasticaClient();
$elasticaIndex = $elasticaClient->getIndex($this->getIndexName());
$elasticaQuery = new Elastica\Query\BoolQuery();
$queryAnd = new \Elastica\Query\BoolQuery();
$queryOr = new \Elastica\Query\BoolQuery();
$queryOr->addShould(new \Elastica\Query\Wildcard('search_field1', $keyword));
$queryOr->addShould(new \Elastica\Query\Wildcard('search_field2', $keyword));
$queryAnd->addMust($queryOr);
$elasticaQuery->addFilter($queryAnd);
$mainQuery = new \Elastica\Query();
$mainQuery->setQuery($elasticaQuery);
$elasticaResultSet = $elasticaIndex->search($mainQuery);
I get a bunch of results back, but always the _score for those results is 0, even if i enter the full word that can be found in the stored field(for a full match).
The mapping for the field is pretty simple:
'search_field1' => array(
'type' => 'string',
'include_in_all' => true,
'analyzer' => 'stringLowercase',
),
The stringLowercase analyzer is just:
'stringLowercase' => array(
'type' => 'custom',
'tokenizer' => 'keyword',
'filter' => 'lowercase'
),
Moreover, even if i try to boost either of the fields, it does not seem to have any effect.
Can anybody shed some light over this?
have you tried to query something nested like this?:
//i.e.
$queryField = new \Elastica\Query\QueryString($query);
$queryField->setDefaultOperator('OR');
$queryBool->addMustNot($queryField);
//then
$queryOr = new \Elastica\Query\Wildcard('search_field1', $keyword);
$queryOr->addShould($queryBool);

Group By within contain cakephp

Hellow , I want to use group by within contain in cakephp. In the following case i want to take only distinct organization within organizationUser array..
$options = array(
'conditions' => array('User.' .$this->User->primaryKey => $userId),
'contain' => array(
'OrganizationUser'=>array(
'conditions'=>['status'=>3],
'group'=> array( 'OrganizationUser.organization_id')),
'OrganizationUser.Organization',
'OrganizationUser.Organization.Noticeboard',
'OrganizationUser.Organization.Newsboard',
'OrganizationUser.Organization.Noticeboard.Branch',
),
'page'=>$page,
'limit'=>$limit
);
$org = $this->User->find('all', $options);
But this is throwing error like 'Column not found', and 'conditions' is working fine within OrganizationUser but 'group' not working.I am using cakephp version 2.Thanks in advance.
I don't think cakephp 2+ offer something like you are doing to make field distinct within contain. So better to try following..
Replace :
'group'=> array( 'OrganizationUser.organization_id')
By
'fields'=> array( 'DISTINCT OrganizationUser.organization_id')
that might work for you.
In my case, I'm using cake version 4+.
In my table the relation I've made
$this->belongsTo('CreatedOperator')
->setClassName(USERS_PLUGIN . '.Users')
->setForeignKey('created_by')
->setJoinType('INNER')
;
and I'm calling the relation like
$query
->disableHydration()
->select([
'CreatedOperator.id',
'CreatedOperator.first_name',
'CreatedOperator.last_name',
'full_name' => $query->func()->concat(['CreatedOperator.first_name' => 'identifier',' ','CreatedOperator.last_name' => 'identifier']),
'total' => $query->func()->count('CreatedOperator.id')])
->contain(['CreatedOperator'])
->group(['CreatedOperator.id'])
;
return $query->toList();

Adding query clause to cakephp find operation

I have a standard find query on my user model that looks as followed:
$user = $this->User->find( 'all', array( 'conditions' => array( 'User.id' => $user_id ) ) );
I also have some extensions I would like to make to the where clause of this function call like so:
$query_extension = 'AND users.id IN ( complex join between a few tables )';
I want to add this complex WHERE clause on to the end of that user find condition, but I'm not sure how to do this. I'm looking into the ConnectionManager class, but I'm still not sure how to append this extra clause:
http://api.cakephp.org/2.5/class-ConnectionManager.html#_getDataSource
Check sample code I used, you can also set dynamic content like joins Will have array What you built Or
will have blank array.
$courseNames = $this->UsersCourse->Course->find('list',
array('fields'=> array('Course.course_name'),
'order'=> array('Course.course_name'),
'conditions'=>array('Course.is_active'=>1 ,
'CourseCategory.is_active'=>1
),
"joins" => array(
array(
"table" => "course_categories",
"alias" => "CourseCategory",
"type" => "INNER",
"conditions" => array(
"CourseCategory.id = Course.course_category_id"
)
)
)
)
);
This is how this operation can be preformed. Notice that the clause being added to the main query includes an AND This means that it is actually part of the where clause and can be added as a string to a find as followed.
// Note here that including the $complex_subselect_string as an un-keyed term in the conditions automatically ANDs this extra query clause
$complete_user_list = $this->find( 'all', array( 'conditions' => array( $complex_subselect_string ), 'limit' => $limit, 'contain' => array() ) );

Cakephp check if record exists

I am wondering, is there a function that allows me to check instantly if a record in the database exists?
Right now I am using the following piece of code to detect if a record exists, but I can imagine there is a simpler/better way.
$conditions = array(
'conditions' => array(
'User.id' => $this->Session->read('User.id'),
'User.activation_key' => $this->Session->read('User.key')
)
);
$result = $this->User->find('first', $conditions);
if (isset($result['User'])){
//do something
}
Is there something like:
$conditions = array(
'conditions' => array(
'User.id' => $this->Session->read('User.id'),
'User.security_key' => $this->Session->read('User.key')
)
);
if ($this->User->exists($conditions)){
//do something
}
Okay, yes there is. It's called exists(), but I need the same, but with parameters, so I can add my own conditions to the check.
I have searched google, but I can't find any topic about this. Well, a lot about php and mysql, but not about cakephp. I need a cake specific answer.
Thanks for your time :)
What you are looking for is Model::hasAny
Usage:
$conditions = array(
'User.id' => $this->Session->read('User.id'),
'User.security_key' => $this->Session->read('User.key')
);
if ($this->User->hasAny($conditions)){
//do something
}

cakephp and SQL_CALC_FOUND_ROWS

I am trying to add the SQL_CALC_FOUND_ROWS into a query (Please note this isn't for pagination)
please note I am trying to add this to a cakePHP query the code I currently have is below:
return $this->find('all', array(
'conditions' => $conditions,
'fields'=>array('SQL_CALC_FOUND_ROWS','Category.*','COUNT(`Entity`.`id`) as `entity_count`'),
'joins' => array('LEFT JOIN `entities` AS Entity ON `Entity`.`category_id` = `Category`.`id`'),
'group' => '`Category`.`id`',
'order' => $sort,
'limit'=>$params['limit'],
'offset'=>$params['start'],
'contain' => array('Domain' => array('fields' => array('title')))
));
Note the 'fields'=>array('SQL_CALC_FOUND_ROWS',' this obviously doesn't work as It tries to apply the SQL_CALC_FOUND_ROWS to the table e.g. SELECTCategory.SQL_CALC_FOUND_ROWS,
Is there anyway of doing this? Any help would be greatly appreciated, thanks.
You may want to look at cakephp paginate using mysql SQL_CALC_FOUND_ROWS. The person had similar syntax as you have and it worked for him.
If that doesn't help you can always use $this->find('count', $params); (http://book.cakephp.org/view/1020/find-count) or $this->query('YOUR SQL QUERY HERE'); (http://book.cakephp.org/view/1027/query).
Besides that you should not use 'joins' together with 'contain'. According to the documentation that "could lead to some SQL errors (duplicate tables), so you need to use the joins method as an alternative for Containable".
Maybe you can make your field parameter as below:
'fields'=>array('SQL_CALC_FOUND_ROWS *','COUNT(`Entity`.`id`) as `entity_count`')
This is a horrible, horrible hack to get an unescaped SQL_CALC_FOUND_ROWS into the query, but it works:
$categories = $this->Category->find('all', array(
'fields' => array('SQL_CALC_FOUND_ROWS 0.0 AS dummy_field,1', 'Category.*', ...),
'limit' => 42,
...
));
$totalCategories = $this->Category->query('SELECT FOUND_ROWS() as `total_categories`');
All credit goes to "Kani" from http://mogura.in/blog/2011/06/17/cakephp-1-3-sql_calc_found_rows.
I found a way to realize it with cake built in functions.
$dbo = $this->User->getDataSource();
//buildStatement() creates a Standard SQL Statement
$subQuery = $dbo->buildStatement(
array(
'fields' => $fields,
'table' => $dbo->fullTableName($this->User),
'alias' => 'User',
'limit' => null,
'offset' => null,
'joins' => array(),
'conditions' => $conditions,
'order' => null,
'group' => null
),
$this->User
);
//Add the SQL_CALC_FOUND_ROWS part
$subQuery = str_replace('SELECT', 'SELECT SQL_CALC_FOUND_ROWS', $subQuery);
$Users = $this->User->query($subQuery);
//Get FOUND ROWS
$foundRows = $this->User->query("SELECT FOUND_ROWS()");
$count = intval($foundRows[0][0]['FOUND_ROWS()']);

Categories