Skip to content

Commit

Permalink
Fixed search service
Browse files Browse the repository at this point in the history
  • Loading branch information
Viburnum committed Jun 27, 2016
1 parent f295cc7 commit 25879f9
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 43 deletions.
8 changes: 5 additions & 3 deletions Model/KnpResultSet.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class KnpResultSet extends ResultSetAdapter implements PaginatableResultSet {
use ContainerAwareTrait;

protected $query = null;

protected $term = null;

/**
Expand Down Expand Up @@ -71,7 +71,9 @@ public function getResults($offset = 0, $limit = null) {
*
* @see \StingerSoft\EntitySearchBundle\Model\ResultSet::getExcerpt()
*/
public function getExcerpt(Document $document) {
return Utils::highlight(Utils::excerpt($document->getFieldValue(BaseDocument::FIELD_CONTENT), $this->term), $this->term);
public function getExcerpt(BaseDocument $document) {
$content = $document->getFieldValue(BaseDocument::FIELD_CONTENT);
$content = !is_array($content) ? $content : implode(' ', $content);
return Utils::highlight(Utils::excerpt($content, $this->term), $this->term);
}
}
124 changes: 84 additions & 40 deletions Services/SearchService.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,17 @@
use StingerSoft\EntitySearchBundle\Services\AbstractSearchService;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
use StingerSoft\EntitySearchBundle\Model\Result\FacetSetAdapter;
use Doctrine\ORM\QueryBuilder;
use StingerSoft\EntitySearchBundle\Model\Result\FacetSet;

class SearchService extends AbstractSearchService {

use ContainerAwareTrait;

const BATCH_SIZE = 50;

protected static $highlightStartTag = '<em>';

protected static $highlightEndTag = '</em>';

protected $documentClazz = null;
Expand Down Expand Up @@ -122,7 +124,7 @@ public function autocompleteOrm(EntityManager $em, $search, $maxResults = 10) {
$qb->setParameter('titleFieldName', \StingerSoft\EntitySearchBundle\Model\Document::FIELD_TITLE);
$qb->orWhere('field.fieldName = :contentFieldName AND field.internalFieldValue LIKE :term');
$qb->setParameter('contentFieldName', \StingerSoft\EntitySearchBundle\Model\Document::FIELD_CONTENT);
$qb->setParameter('term', '%'.$search . '%');
$qb->setParameter('term', '%' . $search . '%');
$iterator = $qb->getQuery()->iterate(null, \Doctrine\ORM\Query::HYDRATE_SCALAR);
$suggestions = array();
foreach($iterator as $res) {
Expand All @@ -149,7 +151,7 @@ public function search(Query $query) {
return null;
}

protected function searchOrm(Query $query, EntityManager $em) {
protected function createBasicSearchOrmQuery(Query $query, EntityManager $em) {
$term = $query->getSearchTerm();
$docRepos = $em->getRepository($this->documentClazz);
$qb = $docRepos->createQueryBuilder('doc');
Expand All @@ -160,55 +162,97 @@ protected function searchOrm(Query $query, EntityManager $em) {
}
$qb->setParameter('term', '%' . $term . '%');
$qb->distinct();

$facetedQb = clone $qb;
return $qb;
}

protected function createFacetedOrmQuery(QueryBuilder $qb, Query $query, EntityManager $em) {
$docRepos = $em->getRepository($this->documentClazz);
$facetedQb = $docRepos->createQueryBuilder('facetDoc');
$facetedQb->leftJoin('facetDoc.internalFields', 'facetField');
if($query->getFacets() !== null && count($query->getFacets()) > 0) {
foreach($query->getFacets() as $facetField => $facetValues) {
if($facetValues === null || count($facetValues) == 0)
continue;
$facetedQb->andWhere('field.fieldName = :' . $facetField . 'FacetFieldName AND field.internalFieldValue IN :' . $facetValues . 'FacetFieldValues');
$qb->setParameter($facetField . 'FacetFieldName', $facetField);
$qb->setParameter($facetField . 'FacetFieldValues', $facetValues);

if($facetField == \StingerSoft\EntitySearchBundle\Model\Document::FIELD_TYPE) {
$facetedQb->andWhere('facetDoc.entityClass in (:clazzes)');
$facetedQb->setParameter('clazzes', $facetValues);
} else {
$facetedQb->andWhere('(facetField.fieldName = :' . $facetField . 'FacetFieldName AND facetField.internalFieldValue IN (:' . $facetField . 'FacetFieldValues))');
$facetedQb->setParameter($facetField . 'FacetFieldName', $facetField);
$facetedQb->setParameter($facetField . 'FacetFieldValues', $facetValues);
}
}
}

$result = new KnpResultSet($facetedQb, $term);
$result->setContainer($this->container);

$facetQb = clone $qb;
$facetQb->select('field.fieldName');
$facetQb->addSelect('field.internalFieldValue');
$facetQb->addSelect('COUNT(doc.id) as resultCount');
$facetQb->addGroupBy('field.fieldName');
$facetQb->addGroupBy('field.internalFieldValue');
$facetQb->orderBy('resultCount', 'DESC');

if($query->getUsedFacets() !== null) {
$facetQb->andWhere('field.fieldName IN (:fields)');
$facetQb->setParameter('fields', $query->getUsedFacets());
}

$facetSet = new FacetSetAdapter();
if($query->getUsedFacets() === null || count($query->getUsedFacets()) > 0) {
$this->addResultIdInPart($facetedQb, $query, $em);
return $facetedQb;
}

protected function fetchTypeFacetsFromOrmQuery(FacetSet $facets, Query $query, EntityManager $em) {
if($query->getUsedFacets() === null || in_array(\StingerSoft\EntitySearchBundle\Model\Document::FIELD_TYPE, $query->getUsedFacets())) {
$docRepos = $em->getRepository($this->documentClazz);
$facetQb = $docRepos->createQueryBuilder('facetDoc');
$facetQb->select('facetDoc.entityClass');
$facetQb->addSelect('COUNT(DISTINCT facetDoc.id) as resultCount');
$facetQb->addGroupBy('facetDoc.entityClass');
$facetQb->orderBy('resultCount', 'DESC');
$this->addResultIdInPart($facetQb, $query, $em);
foreach($facetQb->getQuery()->getScalarResult() as $facetResult) {
$facetSet->addFacetValue($facetResult['fieldName'], $facetResult['internalFieldValue'], $facetResult['resultCount']);
$facets->addFacetValue('type', $facetResult['entityClass'], $facetResult['resultCount']);
}

if($query->getUsedFacets() === null || in_array('type', $query->getUsedFacets())) {
$facetQb = clone $qb;
$facetQb->select('doc.entityClass');
$facetQb->addSelect('COUNT(doc.id) as resultCount');
$facetQb->addGroupBy('doc.entityClass');
$facetQb->orderBy('resultCount', 'DESC');

foreach($facetQb->getQuery()->getScalarResult() as $facetResult) {
$facetSet->addFacetValue('type', $facetResult['entityClass'], $facetResult['resultCount']);
}
}
}

protected function fetchCommonFacetsFromOrmQuery(FacetSet $facets, Query $query, EntityManager $em) {
if($query->getUsedFacets() === null || count($query->getUsedFacets()) > 0) {
$docRepos = $em->getRepository($this->documentClazz);
$facetQb = $docRepos->createQueryBuilder('facetDoc');
$facetQb->leftJoin('facetDoc.internalFields', 'facetField');
$facetQb->select('facetField.fieldName');
$facetQb->addSelect('facetField.internalFieldValue');
$facetQb->addSelect('COUNT(facetDoc.id) as resultCount');
$facetQb->addGroupBy('facetField.fieldName');
$facetQb->addGroupBy('facetField.internalFieldValue');
$facetQb->orderBy('resultCount', 'DESC');

if($query->getUsedFacets() !== null) {
$facetQb->andWhere('facetField.fieldName IN (:facetFields)');
$facetQb->setParameter('facetFields', $query->getUsedFacets());
}
$this->addResultIdInPart($facetQb, $query, $em);
foreach($facetQb->getQuery()->getScalarResult() as $facetResult) {
$facets->addFacetValue($facetResult['fieldName'], $facetResult['internalFieldValue'], $facetResult['resultCount']);
}
}
}

protected function addResultIdInPart(QueryBuilder $queryToAdd, Query $query, EntityManager $em, $docAlias = 'facetDoc') {
$inQuery = $this->createBasicSearchOrmQuery($query, $em);
$inQuery->select('doc.id');
$queryToAdd->andWhere($queryToAdd->expr()->in($docAlias.'.id', $inQuery->getQuery()->getDQL()));

$result->setFacets($facetSet);
foreach(self::$searchableFields as $field) {
$queryToAdd->setParameter($field . 'FieldName', $field);
}
$queryToAdd->setParameter('term', '%' . $query->getSearchTerm() . '%');
}

protected function searchOrm(Query $query, EntityManager $em) {
// Simple Like query
$qb = $this->createBasicSearchOrmQuery($query, $em);

// Adds facets if available
$facetedQb = $this->createFacetedOrmQuery($qb, $query, $em);

$result = new KnpResultSet($facetedQb, $query->getSearchTerm());
$result->setContainer($this->container);

$facetSet = new FacetSetAdapter();
$this->fetchTypeFacetsFromOrmQuery($facetSet, $query, $em);
$this->fetchCommonFacetsFromOrmQuery($facetSet, $query, $em);

$result->setFacets($facetSet);

return $result;
}
Expand Down

0 comments on commit 25879f9

Please sign in to comment.