我的Service
实体包含title
,tags
和description
字段。使用QueryBuilder搜索服务时,如何按字段优先级排序结果。例如,当我搜索字词php
时,我希望在列表顶部的标题中获得php
的服务,然后在其标记和服务中使用php
的服务,其中包含搜索字词描述为最后一个。
这是我的Querybuilder的一部分:
$qb = $this->createQueryBuilder('service');
$qb->leftJoin('service.tags', 'tag');
$conditions = array($conditions[] = $qb->expr()->eq('service.enabled', true));
$conditions[] = $qb->expr()->eq('service.category', $categoryId);
$term = '%' . $term . '%';
$conditions[] = $qb->expr()->orX(
$qb->expr()->like('service.title', "'$term'"),
$qb->expr()->like('service.description', "'$term'"),
$qb->expr()->like('tag.name', "'$term'")
);
$conditions = call_user_func_array(array($qb->expr(), 'andX'), $conditions);
$qb->where($conditions);
答案 0 :(得分:4)
执行此操作的最佳方法是执行一系列UNION
语句,然后在给出重量的同时清除重复项。
(未经检查的伪SQL提供了这个想法):
SELECT id,title,tag,SUM(weight) score
FROM (
SELECT id,title,tag, 100 as weight FROM service WHERE title LIKE '%foo%'
UNION ALL
SELECT id,title,tag, 10 as weight FROM service WHERE tags LIKE '%foo%'
UNION ALL
SELECT id,title,tag, 1 as weight FROM service WHERE description LIKE '%foo%'
) t
GROUP BY id
ORDER BY score DESC /* This sort by probably won't work; might need to do it a different way, but you get the idea */
答案 1 :(得分:2)
您可以使用本机查询。例:
$em = $this->get('doctrine')->getManager();
$sql = "
select *
from service s
where
s.title like '%xxx%'
or s.tags like '%xxx%'
or s.description like '%xxx%'
order by
s.title like '%xxx%' desc,
s.tags like '%xxx%' desc,
s.description like '%xxx%' desc
";
$rsm = new \Doctrine\ORM\Query\ResultSetMappingBuilder($em);
$rsm->addRootEntityFromClassMetadata('\You\Entity\Service\Class', 's');
$query = $em->createNativeQuery($sql, $rsm);
$data = $query->getResult();
dump($data);
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/native-sql.html如何在orm
中使用dql的sql答案 2 :(得分:1)
我不会尝试在只有一个查询中获得所需的结果。它太复杂了,你花了很多时间尝试得到你想要的东西。
首先,我假设您希望获得{em>排序数组的lme4
实体,如下所示:
Service
所以你可以简单地通过它迭代(foreach)
如果是这种情况,请遵循以下标准:
并且在您的/** @var Service[] $results **/
$results = $this->getDoctrine()->getManager()->getRepository('YourBundle:YourServiceRepo')->findSerivesByGivenSerchCriteria($yourConditions);
方法中,您可以调用其中的所有三个,并且可以按照我喜欢的任何顺序合并找到的结果
例如:
findSerivesByGivenSearchCriteria()
获得" uniqness"尝试结合Doctrine的public function findSerivesByGivenSerchCriteria( $searchTirm ) {
$foundServicesByTitle = $this->findServicesBySearchCriteriaInTitle( $searachTirm );
$foundServicesByTag = $this->findServicesBySearchCriteriaInTags( $searchTirm );
$foundServicesByDesc = $this->findServicesBySearchCriteriaInDesc( $searchTirm );
// Hier you can combine found results in any order
$results = [];
if( false === empty($foundServicesByTitle ) )
{
// for example with array_merge ...
// NOTE: If you choose array_merge() you have to make sure your $foundServicesByTitle, $foundServicesByTag, $foundServicesByDesc have unique array-indexes
// And you get Results like
// array( 'unique_id_1' => ServiceEntity, 'unique_id_2' => ServiceEntity ... )
$results = array_merge($results, $foundServicesByTitle);
}
// .. do the same with other two
return $results;
}
和INDEX BY
HIDDEN
- > http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html#using-index-by
INDEX BY
- > https://stackoverflow.com/a/15120793/348193
INDEX BY
- > https://michelsalib.com/2012/03/04/doctrine2-ninja-with-the-hidden-keyword/
HIDDEN
方式?因为你使用symfony和doctrine UNION
并不是最好的方法。见How to write UNION in Doctrine 2.0
正如您所看到的,UNION
不受Doctrine 支持,您必须使用UNION
(这可能会让NativeQuery
感到沮丧核心映射并将原始结果转换为所需的实体)