Elasticsearch bundle requires mapping definitions in order for it to work with complex operations, like insert and update documents, do a full text search and etc.
Here's an example of configuration containing the definitions of filter and analyzer:
ongr_elasticsearch:
analysis:
filter:
incremental_filter:
type: edge_ngram
min_gram: 1
max_gram: 20
analyzer:
incrementalAnalyzer:
type: custom
tokenizer: standard
filter:
- lowercase
- incremental_filter
connections:
default:
index_name: acme_index
analysis:
analyzer:
- incrementalAnalyzer
filter:
- incremental_filter
managers:
default:
connection: default
mappings:
- AppBundle
At the very top you can see analysis
node. This is for holding a filters, analyzers, tokenizers and other analyzation kind stuff for your connections. So lets assume you defined custom incrementalAnalyzer
analyzer. The key stands as analyzer name, so down below in default
connection's analysis
section you can add this analyzer to include in certain connection mapping. And all you need to do is only to add the name. So now when you have defined a custom analyzer, you can use it in some document fields, see below in the document's examples how to do that.
In the managers configuration mappings
is optional. If there are no mappings defined, it will look up through Document
folders contained in the all bundles.
Lets start with a document class example.
// src/AppBundle/Document/Content.php
namespace AppBundle/Document;
use ONGR\ElasticsearchBundle\Annotation as ES;
/**
* @ES\Document(type="content")
*/
class Content
{
/**
* @var string
*
* @ES\Id()
*/
public $id;
/**
* @ES\Property(type="string")
*/
public $title;
}
-
@ES\Document(type="content")
Annotation defines that this class will represent elasticsearch type with namecontent
. -
type
parameter is for type name. This parameter is optional, if there will be no parameter set Elasticsearch bundle will create a type with lowercased class name.
To define type properties there is @ES\Property
annotation. The only required
attribute is type
- Elasticsearch field type to define what kind of information
will be indexed. By default field name is generated from property name by converting
it to "snake case" string. You can specify custom name by setting name
attribute.
To add custom settings to property like analyzer it has to be included in options
. Analyzers names is the same that was defined in config.yml
analysis
section [before](#Mapping configuration). Here's an example how to add it:
// src/AppBundle/Document/Content.php
namespace AppBundle/Document;
use ONGR\ElasticsearchBundle\Annotation as ES;
/**
* @ES\Document(type="content")
*/
class Content
{
// ...
/**
* @ES\Property(
type="string",
name="original_title",
options={"analyzer":"incrementalAnalyzer"}
)
*/
public $title;
}
options
container accepts any parameters. We leave mapping validation to elasticsearch and elasticsearch-php client, if there will be a mistake index won't be created due exception.
It is a little different to define nested and object types. For this user will need to create a separate class with object annotation. Lets assume we have a Content type with object field.
// src/AppBundle/Document/Content.php
namespace AppBundle/Document;
use ONGR\ElasticsearchBundle\Annotation as ES;
/**
* @ES\Document(type="content")
*/
class Content
{
/**
* @ES\Property(type="string")
*/
public $title;
/**
* @var ContentMetaObject
*
* @ES\Embedded(class="AppBundle:ContentMetaObject")
*/
public $metaObject;
}
And the content object will look like:
// src/AppBundle/Document/ContentMetaObject.php
namespace AppBundle/Document;
use ONGR\ElasticsearchBundle\Annotation as ES;
/**
* @ES\Object
*/
class ContentMetaObject
{
/**
* @ES\Property(type="string")
*/
public $key;
/**
* @ES\Property(type="string")
*/
public $value;
}
As shown in the example, by default only a single object will be saved in the document.
If there is necessary to store a multiple objects (array), add multiple=true
. While
initiating a document with multiple items you need to initialize property with new instance of Collection
.
// src/AppBundle/Document/Content.php
namespace AppBundle/Document;
use ONGR\ElasticsearchBundle\Annotation as ES;
use ONGR\ElasticsearchBundle\Collection;
/**
* @ES\Document(type="content")
*/
class Content
{
// ...
/**
* @var ContentMetaObject[]|Collection
*
* @ES\Embedded(class="AppBundle:ContentMetaObject", multiple="true")
*/
public $metaObjects;
/**
* Initialize collection.
*/
public function __construct()
{
$this->metaObjects = new Collection();
}
}
Insert action will look like this:
<?php
$content = new Content();
$content->metaObjects[] = new ContentMetaObject();
$content->metaObjects[] = new ContentMetaObject();
$manager->persist($content);
$manager->commit();
To define object or nested fields use @ES\Embedded
annotation. In the objects there is possibility to define other objects also.
Nested types can be defined the same way as objects, except
@ES\Nested
annotation must be used.
Read dedicated page about meta-field annotations here.
More information about mapping can be found in the Elasticsearch mapping documentation.