$dm = $this->get('doctrine.odm.mongodb.document_manager');
$query = $dm->createQueryBuilder('MyBundle:Listing')
->select('title')
->field('coordinates')->geoNear(
(float)$longitude,
(float)$latitude
)->spherical(true);
$classifieds_array = $classifieds->toArray();
$data = array('success'=>true,'classifieds' => $classifieds_array,
'displaymessage' => $classifieds->count(). " Search Results Found");
Even though I am selecting just one field, for my result set, I am getting every thing back in collection along with title. Is this a bug?
NOTE: I commented out the ->field('coordinates')->geoNear((float)$longitude, (float)$latitude)->spherical(true) line and now the select seems to work. This is crazy.
The geoNear command in MongoDB doesn't seem to support filtering result fields, according to the documentation examples. Only a query option is supported to limit matched documents.
In your case, it also looks like mixing up the geoNear() and near() builder methods in Doctrine. Since you're operating on the coordinates field, the appropriate syntax would be near(). geoNear() is a top-level method to tell the builder you wish to use the command, which doesn't require a field name since it uses the one and only geospatial index on the collection.
For usage examples, I would advise looking at the query and builder unit tests in the Doctrine MongoDB library.
Related
Using this code within a Repo
$builder = $this->createQueryBuilder("s");
$builder->addOrderBy("s.name", "ASC");
$pagi = new Paginator($builder->getQuery(), true);
$data = $pagi->getIterator()->getArrayCopy();
Results in this error
SQLSTATE[HY000]: General error: 3065 Expression #1 of ORDER BY clause
is not in SELECT list, references column 'dctrn_result.name_5' which
is not in SELECT list; this is incompatible with DISTINCT") in
AppBundle:Schools/Search:results_list.html.twig at line 33.
name is a valid column name for the s table. This did work but moving to a new machine and installing a new version of MySQL has broken this completely. There are some references to this issue http://www.doctrine-project.org/jira/browse/DDC-1800
But no actual solution other than removing the s. which also fails
$builder->addOrderBy("name", "ASC");
I am a complete loss of what to do, as this seems to be a fairly major issue within Doctrine2's paginator.
I am using MySQL 5.7.9.
For given error, explicit select statement should do the job.
$builder = $this->createQueryBuilder("s");
$builder->select("s")
->orderBy("s.name", "ASC");
But I would recommend using KnpPaginatorBundle if you want to use pagination in many different cases. That component is more flexible.
I think you must downgrade your mySql version to 5.6
I have a query that returns roughly 6,000 results. Although this query executes in under a second in MySQL, once it is run through Zend Framework 2, it experiences a significant slowdown.
For this reason, I tried to do it a more "raw" way with PDO:
class ThingTable implements ServiceLocatorAwareInterface
{
// ...
public function goFast()
{
$db_config = $this->getServiceLocator()->get('Config')['db'];
$pdo = new PDO($db_config['dsn'], $db_config['username'], $db_config['password']);
$statement = $pdo->prepare('SELECT objectNumber, thingID, thingmaker, hidden, title FROM Things ', array(PDO::MYSQL_ATTR_COMPRESS, PDO::CURSOR_FWDONLY));
$statement->execute();
return $statement->fetchAll(PDO::FETCH_ASSOC);
}
}
This doesn't seem to have much of a speedup, though.
I think the problem might be that Zend is still trying to create a new Thing object for each record, even though it is only a partial list of columns. I'd really be okay not populating any objects. I really just need a few columns with those attributes to iterate over.
As suggested by user MonkeyZeus, the following was used for bench-marking:
$start = microtime(true);
$result = $statement->fetchAll(PDO::FETCH_ASSOC);
echo (microtime(true) - $start).' seconds';
And in response:
In a VM, that returns 0.0050520896911621. This is in line with what it
is when I just run the command straight in MySQL. I believe the
overhead is in Zend, but not sure how to quite go about that. Again if
I had to guess, I'd say it is because Zend is adding overhead while
trying to be nice with the results, but I'm not quite sure how to
proceed after that.
[I'm] not so worried about the query. It is a single select statement.
goFast() gets called by the Zend indexAction() --similar to other
actions used across the project--this one is just way slower at
returning the page. One problem I found was that Zend's $this->url()
was slowing things down a bit. So I removed those, but the performance
still isn't great.
How can I speed this up?
When you say , that query runs under a second in MySQL , what do you mean ? did you try to run this query and print ALL 6000 rows ? or you just queried this and command line printed first/last few of them ?
The problem might be that , you are fetching them all , going through cursor , you are copying all the data ( 6000 rows ) from MySQL to PHP and then returning it , are you sure you want to do this ?
Maybe you could return a statement/cursor to the Query and then iterate through rows when you really need it ?
Your problem is not the SQL itself , but fetching them into PHP array all at once.
You can test it by logging the time it needs to actually execute SQL and fetching it into PHP array.
Do not use fetchall , return the statement itself and in the function/code where you have to run "foreach" this array , use statement to fetch each row one by one.
I had the need to include in one of my system's DQL queries, a subquery with LIMIT clause. As Doctrine doesn't support it, I changed it to a native query. Yet the native query is returning lower case fields instead of the correct case.
The case is that as this is working code, I had some views depending on this names and it's much harder to change all names.
But I found here http://bit.ly/1Ht1ojH, that this aspect can be configured in Doctrine. So I tried this code:
$conn = $this->getConnection();
$conn->setAttribute(Doctrine_Core::ATTR_FIELD_CASE, CASE_NATURAL);
$res = $conn->query("select MyCasedField from whatever")->fetchAll();
Yet I'm getting the error "Attempted to call method "setAttribute" on class "Doctrine\ORM\EntityManager".
I tried with manager also with same result.
Now I now I can make some code to translate the fields, but I find that the configure solution to be much more clean.
Someone knows why symfony doesn't let me configure the connection ?
Also if there is any way of using LIMIT in a DQL's subquery I would find it better.
There is no LIMIT keyword in DQL. To use this functionality you can call method setMaxResults($limit) on your query object. It is also can be applied to Query Builder.
$query = $this->getEntityManager()
->createQuery('SELECT p FROM Product p')
->setMaxResults($limit);
I am trying to use Query Builder in Symfony2 to get some records from a database. I run the normal query in SQL and it returns the correct results. The query is
SELECT pg.name, pg.description
FROM pm_patentgroups pg
LEFT JOIN pm_portfolios pp ON pp.id = pg.portfolio_id
I want to use the exact query using Doctorine query builder in Symfony2. What I have tried so far is
$repository = $this->getDoctrine()
->getRepository('MunichInnovationGroupBundle:PmPatentgroups');
$query = $repository->createQueryBuilder('pg')
->from('pm_patentgroups', 'pg')
->leftJoin('pg','pm_portfolios','pp','pp.id = pg.portfolio_id')
->getQuery();
$portfolio_groups = $query->getResult();
but its giving me the following error:
Warning: Missing argument 1 for Doctrine\ORM\EntityRepository::createQueryBuilder()
I am new to Symfony2 and Doctorine. Can you please tell me what is going wrong here?
Thanks
You are missing the alias when using createQueryBuilder. Since you have the repository you can drop the from portion and just use
$query = $repository->createQueryBuilder('pg')
Something like:
$qb = $this->getDoctrine()->createQueryBuilder();
$qb->addSelect('pm_patentgroups');
$qb->addSelect('pm_portfolios');
$qb->from('MunichInnovationGroupBundle:PmPatentgroups','pm_patentgroups');
$qb->leftJoin('pm_patentgroups.pm_portfolios','pm_portfolios');
This assumes you have your two entities properly related.
Lots of examples in the D2 manual. Just keep in mind that query builder works with objects, not sql.
And by the way, your error message comes from the fact that the entity repository (as opposed to the entity manager) requires an alias.
I am using zend search lucene, and would like to add boosts to some of my search terms.
The code is already written using the query construction API as follows.
$query->addTerm(new Zend_Search_Lucene_Index_Term($name,'name'), null);
I tried writing
$query->addTerm(new Zend_Search_Lucene_Index_Term($name . "^10", 'name'), null);
But that appears not to work correctly. (I suddenly get no results at all).
This carat syntax is listed in the documentation for query language, but not in the docs for query construction API. I know that in some instances the API doesn't behave quite like plain query language. Is this one of those instances?
Is there a function or parameter that adds boost values to terms?
Try outputting your query by doing something like this:
$term = new Zend_Search_Lucene_Index_Term($name,'name');
$query = new Zend_Search_Lucene_Search_Query_Term($term);
echo $query;
This will allow you to see the query that is being created before you use it to execute a search.