Skip to content

Commit

Permalink
Merge pull request ezsystems#1051 from ezsystems/impl-EZP-23396-elast…
Browse files Browse the repository at this point in the history
…icsearch-fulltext

Implement EZP-23396: Elasticsearch: Implement Fulltext criterion for Content search
  • Loading branch information
pspanja committed Oct 24, 2014
2 parents cc82e41 + d4d2c15 commit 63eb63c
Show file tree
Hide file tree
Showing 7 changed files with 290 additions and 9 deletions.
@@ -0,0 +1,38 @@
<?php

return eZ\Publish\API\Repository\Values\Content\Search\SearchResult::__set_state(array(
'facets' =>
array (
),
'searchHits' =>
array (
0 =>
eZ\Publish\API\Repository\Values\Content\Search\SearchHit::__set_state(array(
'valueObject' =>
array (
'id' => 54,
'title' => 'eZ Publish Demo Design (without demo content)',
),
'score' => 0.49063533999999998,
'index' => NULL,
'highlight' => NULL,
)),
1 =>
eZ\Publish\API\Repository\Values\Content\Search\SearchHit::__set_state(array(
'valueObject' =>
array (
'id' => 58,
'title' => 'Contact Us',
),
'score' => 1.0769257999999999,
'index' => NULL,
'highlight' => NULL,
)),
),
'spellSuggestion' => NULL,
'time' => 1,
'timedOut' => NULL,
'maxScore' => 1.0769257999999999,
'totalCount' => 2,
));

@@ -0,0 +1,27 @@
<?php

return eZ\Publish\API\Repository\Values\Content\Search\SearchResult::__set_state(array(
'facets' =>
array (
),
'searchHits' =>
array (
0 =>
eZ\Publish\API\Repository\Values\Content\Search\SearchHit::__set_state(array(
'valueObject' =>
array (
'id' => 58,
'title' => 'Contact Us',
),
'score' => 1.0769257999999999,
'index' => NULL,
'highlight' => NULL,
)),
),
'spellSuggestion' => NULL,
'time' => 1,
'timedOut' => NULL,
'maxScore' => 1.0769257999999999,
'totalCount' => 1,
));

@@ -0,0 +1,27 @@
<?php

return eZ\Publish\API\Repository\Values\Content\Search\SearchResult::__set_state(array(
'facets' =>
array (
),
'searchHits' =>
array (
0 =>
eZ\Publish\API\Repository\Values\Content\Search\SearchHit::__set_state(array(
'valueObject' =>
array (
'id' => 58,
'title' => 'Contact Us',
),
'score' => 1,
'index' => NULL,
'highlight' => NULL,
)),
),
'spellSuggestion' => NULL,
'time' => 1,
'timedOut' => NULL,
'maxScore' => 1,
'totalCount' => 1,
));

@@ -0,0 +1,155 @@
<?php
/**
* File containing the FullText criterion visitor class
*
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
* @version //autogentag//
*/

namespace eZ\Publish\Core\Persistence\Elasticsearch\Content\Search\CriterionVisitor;

use eZ\Publish\Core\Persistence\Elasticsearch\Content\Search\CriterionVisitorDispatcher as Dispatcher;
use eZ\Publish\Core\Persistence\Elasticsearch\Content\Search\CriterionVisitor;
use eZ\Publish\Core\Persistence\Elasticsearch\Content\Search\FieldMap;
use eZ\Publish\API\Repository\Values\Content\Query\Criterion;
use eZ\Publish\API\Repository\Values\Content\Query\CustomFieldInterface;

/**
* Visits the FullText criterion
*/
class FullText extends CriterionVisitor
{
/**
* Field map
*
* @var \eZ\Publish\Core\Persistence\Elasticsearch\Content\Search\FieldMap
*/
protected $fieldMap;

/**
* Create from field map
*
* @param \eZ\Publish\Core\Persistence\Elasticsearch\Content\Search\FieldMap $fieldMap
*/
public function __construct( FieldMap $fieldMap )
{
$this->fieldMap = $fieldMap;
}

/**
* Get field type information
*
* @param \eZ\Publish\API\Repository\Values\Content\Query\CustomFieldInterface $criterion
* @return array
*/
protected function getFieldTypes( CustomFieldInterface $criterion )
{
return $this->fieldMap->getFieldTypes( $criterion );
}

/**
* Check if visitor is applicable to current criterion
*
* @param \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterion
*
* @return boolean
*/
public function canVisit( Criterion $criterion )
{
return $criterion instanceof Criterion\FullText;
}

/**
* Returns nested condition common for filter and query contexts.
*
* @throws \eZ\Publish\Core\Base\Exceptions\InvalidArgumentException If no searchable fields are found for the given criterion target.
*
* @param \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterion
*
* @return array
*/
protected function getCondition( Criterion $criterion )
{
/** @var \eZ\Publish\API\Repository\Values\Content\Query\Criterion\FullText $criterion */
$fields = $this->getFieldTypes( $criterion );

// Add field document custom _all field
$queryFields = array( "fields_doc.meta_all" );

// Add boosted fields if any
foreach ( $criterion->boost as $field => $boost )
{
if ( !isset( $fields[$field] ) )
{
continue;
}

foreach ( $fields[$field] as $fieldNames )
{
foreach ( $fieldNames as $fieldName )
{
$queryFields[] = sprintf( "fields_doc.{$fieldName}^%.1f", $boost );
}
}
}

$condition = array(
"query_string" => array(
"query" => $criterion->value . ( $criterion->fuzziness < 1 ? "~" : "" ),
"fields" => $queryFields,
"fuzziness" => $criterion->fuzziness,
// This one will be heavy, enabled per FullText criterion spec
"allow_leading_wildcard" => true,
// Might make sense to use percentage in addition
"minimum_should_match" => 1,
// Default is OR, changed per FullText criterion spec
"default_operator" => "AND",
),
);

return $condition;
}

/**
* Map field value to a proper Elasticsearch filter representation
*
* @throws \eZ\Publish\Core\Base\Exceptions\InvalidArgumentException If no searchable fields are found for the given criterion target.
*
* @param \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterion
* @param \eZ\Publish\Core\Persistence\Elasticsearch\Content\Search\CriterionVisitorDispatcher $dispatcher
*
* @return mixed
*/
public function visitFilter( Criterion $criterion, Dispatcher $dispatcher = null )
{
return array(
"nested" => array(
"path" => "fields_doc",
"filter" => array(
"query" => $this->getCondition( $criterion ),
),
),
);
}

/**
* Map field value to a proper Elasticsearch query representation
*
* @throws \eZ\Publish\Core\Base\Exceptions\InvalidArgumentException If no searchable fields are found for the given criterion target.
*
* @param \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterion
* @param \eZ\Publish\Core\Persistence\Elasticsearch\Content\Search\CriterionVisitorDispatcher $dispatcher
*
* @return mixed
*/
public function visitQuery( Criterion $criterion, Dispatcher $dispatcher = null )
{
return array(
"nested" => array(
"path" => "fields_doc",
"query" => $this->getCondition( $criterion ),
),
);
}
}
@@ -1,6 +1,7 @@
{
"content": {
"dynamic": false,
"_all" : { "enabled": false },
"properties": {
"id": { "type": "integer", "index": "not_analyzed" },
"type_id": { "type": "string", "index": "not_analyzed" },
Expand Down Expand Up @@ -41,6 +42,7 @@
"type": "nested",
"dynamic": true,
"properties": {
"meta_all": { "type": "string" },
"meta_language_code_s": { "type": "string", "index": "not_analyzed" },
"meta_is_main_translation_b": { "type": "boolean", "index": "not_analyzed" },
"user_first_name_value_ms": { "type": "string", "analyzer": "string_lowercase", "copy_to": "fields_doc.custom_field" },
Expand All @@ -54,55 +56,79 @@
"field_string": {
"path_match": "fields_doc.*_*s",
"match_mapping_type": "string",
"mapping": { "type": "string", "analyzer": "string_lowercase" }
"mapping": {
"type": "string",
"analyzer": "string_lowercase",
"copy_to": "fields_doc.meta_all"
}
}
},
{
"field_id": {
"path_match": "fields_doc.*_id",
"match_mapping_type": "string",
"mapping": { "type": "string", "index": "not_analyzed" }
"mapping": {
"type": "string",
"index": "not_analyzed"
}
}
},
{
"field_integer": {
"path_match": "fields_doc.*_i",
"match_mapping_type": "integer",
"mapping": { "type": "integer", "index": "not_analyzed" }
"mapping": {
"type": "integer",
"index": "not_analyzed"
}
}
},
{
"field_integer": {
"path_match": "fields_doc.*_f",
"match_mapping_type": "float",
"mapping": { "type": "integer", "index": "not_analyzed" }
"mapping": {
"type": "integer",
"index": "not_analyzed"
}
}
},
{
"field_integer": {
"path_match": "fields_doc.*_l",
"match_mapping_type": "long",
"mapping": { "type": "integer", "index": "not_analyzed" }
"mapping": {
"type": "integer",
"index": "not_analyzed"
}
}
},
{
"field_integer": {
"path_match": "fields_doc.*_d",
"match_mapping_type": "double",
"mapping": { "type": "integer", "index": "not_analyzed" }
"mapping": {
"type": "integer",
"index": "not_analyzed"
}
}
},
{
"field_integer": {
"path_match": "fields_doc.*_b",
"match_mapping_type": "boolean",
"mapping": { "type": "boolean", "index": "not_analyzed" }
"mapping": {
"type": "boolean",
"index": "not_analyzed"
}
}
},
{
"field_geo_point": {
"path_match": "fields_doc.*_gl",
"mapping": { "type": "geo_point" }
"mapping": {
"type": "geo_point"
}
}
}
]
Expand Down
Expand Up @@ -7417,7 +7417,7 @@
'contentobject_id' => '54',
'data_float' => '0',
'data_int' => NULL,
'data_text' => 'Shopping basket',
'data_text' => 'Shopping basket content',
'data_type_string' => 'ezstring',
'id' => '202',
'language_code' => 'eng-US',
Expand Down
Expand Up @@ -8,6 +8,7 @@ parameters:
ezpublish.persistence.elasticsearch.search.content.criterion_visitor.custom_field_range.class: eZ\Publish\Core\Persistence\Elasticsearch\Content\Search\CriterionVisitor\CustomField\CustomFieldRange
ezpublish.persistence.elasticsearch.search.content.criterion_visitor.field_in.class: eZ\Publish\Core\Persistence\Elasticsearch\Content\Search\CriterionVisitor\Field\FieldIn
ezpublish.persistence.elasticsearch.search.content.criterion_visitor.field_range.class: eZ\Publish\Core\Persistence\Elasticsearch\Content\Search\CriterionVisitor\Field\FieldRange
ezpublish.persistence.elasticsearch.search.content.criterion_visitor.fulltext.class: eZ\Publish\Core\Persistence\Elasticsearch\Content\Search\CriterionVisitor\FullText
ezpublish.persistence.elasticsearch.search.content.criterion_visitor.date_modified_in.class: eZ\Publish\Core\Persistence\Elasticsearch\Content\Search\CriterionVisitor\DateMetadata\ModifiedIn
ezpublish.persistence.elasticsearch.search.content.criterion_visitor.date_modified_range.class: eZ\Publish\Core\Persistence\Elasticsearch\Content\Search\CriterionVisitor\DateMetadata\ModifiedRange
ezpublish.persistence.elasticsearch.search.content.criterion_visitor.date_published_in.class: eZ\Publish\Core\Persistence\Elasticsearch\Content\Search\CriterionVisitor\DateMetadata\PublishedRange
Expand Down Expand Up @@ -80,6 +81,13 @@ services:
tags:
- {name: ezpublish.persistence.elasticsearch.search.content.criterion_visitor}

ezpublish.persistence.elasticsearch.search.content.criterion_visitor.fulltext:
class: %ezpublish.persistence.elasticsearch.search.content.criterion_visitor.fulltext.class%
arguments:
- @ezpublish.persistence.elasticsearch.search.content.field_map
tags:
- {name: ezpublish.persistence.elasticsearch.search.content.criterion_visitor}

ezpublish.persistence.elasticsearch.search.content.criterion_visitor.date_modified_in:
class: %ezpublish.persistence.elasticsearch.search.content.criterion_visitor.date_modified_in.class%
tags:
Expand Down

0 comments on commit 63eb63c

Please sign in to comment.