Merge remote-tracking branch 'cup-of-giraf/nested'
Conflicts: DependencyInjection/Configuration.php
This commit is contained in:
commit
62b28a813e
|
@ -267,6 +267,13 @@ class Configuration
|
|||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->arrayNode('_parent')
|
||||
->treatNullLike(array())
|
||||
->children()
|
||||
->scalarNode('type')->end()
|
||||
->scalarNode('identifier')->defaultValue('id')->end()
|
||||
->end()
|
||||
->end()
|
||||
->arrayNode('properties')
|
||||
->useAttributeAsKey('name')
|
||||
->prototype('array')
|
||||
|
|
|
@ -40,7 +40,6 @@ abstract class AbstractProvider extends BaseAbstractProvider
|
|||
if ($loggerClosure) {
|
||||
$stepStartTime = microtime(true);
|
||||
}
|
||||
|
||||
$objects = $this->fetchSlice($queryBuilder, $this->options['batch_size'], $offset);
|
||||
|
||||
$this->objectPersister->insertMany($objects);
|
||||
|
|
35
README.md
35
README.md
|
@ -139,6 +139,41 @@ Elasticsearch type is comparable to Doctrine entity repository.
|
|||
|
||||
Our type is now available as a service: `foq_elastica.index.website.user`. It is an instance of `Elastica_Type`.
|
||||
|
||||
### Declaring parent field
|
||||
|
||||
foq_elastica:
|
||||
clients:
|
||||
default: { host: localhost, port: 9200 }
|
||||
indexes:
|
||||
website:
|
||||
client: default
|
||||
types:
|
||||
comment:
|
||||
mappings:
|
||||
post: {_parent: { type: "post", identifier: "id" } }
|
||||
date: { boost: 5 }
|
||||
content: ~
|
||||
|
||||
### Declaring `nested` or `object`
|
||||
|
||||
foq_elastica:
|
||||
clients:
|
||||
default: { host: localhost, port: 9200 }
|
||||
indexes:
|
||||
website:
|
||||
client: default
|
||||
types:
|
||||
post:
|
||||
mappings:
|
||||
date: { boost: 5 }
|
||||
title: { boost: 3 }
|
||||
content: ~
|
||||
comments:
|
||||
type: "nested"
|
||||
properties:
|
||||
date: { boost: 5 }
|
||||
content: ~
|
||||
|
||||
### Populate the types
|
||||
|
||||
php app/console foq:elastica:populate
|
||||
|
|
22
Resetter.php
22
Resetter.php
|
@ -58,7 +58,27 @@ class Resetter
|
|||
|
||||
$type = $indexConfig['index']->getType($typeName);
|
||||
$type->delete();
|
||||
$type->setMapping($indexConfig['config']['mappings'][$typeName]['properties']);
|
||||
$mapping = $this->createMapping($indexConfig['config']['mappings'][$typeName]);
|
||||
$type->setMapping($mapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* create type mapping object
|
||||
*
|
||||
* @param array $indexConfig
|
||||
* @return Elastica_Type_Mapping
|
||||
*/
|
||||
protected function createMapping($indexConfig)
|
||||
{
|
||||
$mapping = \Elastica_Type_Mapping::create($indexConfig['properties']);
|
||||
|
||||
foreach($indexConfig['properties'] as $field => $type) {
|
||||
if (!empty($type['_parent']) && $type['_parent'] !== '~') {
|
||||
$mapping->setParam('_parent', array('type' => $type['_parent']['type']));
|
||||
}
|
||||
}
|
||||
|
||||
return $mapping;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -29,6 +29,17 @@ class ResetterTest extends \PHPUnit_Framework_TestCase
|
|||
),
|
||||
),
|
||||
),
|
||||
'parent' => array(
|
||||
'index' => $this->getMockElasticaIndex(),
|
||||
'config' => array(
|
||||
'mappings' => array(
|
||||
'a' => array('properties' => array(
|
||||
'field_1' => array('_parent' => array('type' => 'b', 'identifier' => 'id')),
|
||||
'field_2' => array())),
|
||||
'b' => array('properties' => array()),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -80,9 +91,10 @@ class ResetterTest extends \PHPUnit_Framework_TestCase
|
|||
$type->expects($this->once())
|
||||
->method('delete');
|
||||
|
||||
$mapping = \Elastica_Type_Mapping::create($this->indexConfigsByName['foo']['config']['mappings']['a']['properties']);
|
||||
$type->expects($this->once())
|
||||
->method('setMapping')
|
||||
->with($this->indexConfigsByName['foo']['config']['mappings']['a']['properties']);
|
||||
->with($mapping);
|
||||
|
||||
$resetter = new Resetter($this->indexConfigsByName);
|
||||
$resetter->resetIndexType('foo', 'a');
|
||||
|
@ -106,6 +118,28 @@ class ResetterTest extends \PHPUnit_Framework_TestCase
|
|||
$resetter->resetIndexType('foo', 'c');
|
||||
}
|
||||
|
||||
public function testIndexMappingForParent()
|
||||
{
|
||||
$type = $this->getMockElasticaType();
|
||||
|
||||
$this->indexConfigsByName['parent']['index']->expects($this->once())
|
||||
->method('getType')
|
||||
->with('a')
|
||||
->will($this->returnValue($type));
|
||||
|
||||
$type->expects($this->once())
|
||||
->method('delete');
|
||||
|
||||
$mapping = \Elastica_Type_Mapping::create($this->indexConfigsByName['parent']['config']['mappings']['a']['properties']);
|
||||
$mapping->setParam('_parent', array('type' => 'b'));
|
||||
$type->expects($this->once())
|
||||
->method('setMapping')
|
||||
->with($mapping);
|
||||
|
||||
$resetter = new Resetter($this->indexConfigsByName);
|
||||
$resetter->resetIndexType('parent', 'a');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Elastica_Index
|
||||
*/
|
||||
|
|
|
@ -92,6 +92,19 @@ class POPO
|
|||
{
|
||||
return $this->file;
|
||||
}
|
||||
|
||||
public function getSub()
|
||||
{
|
||||
return array(
|
||||
(object) array('foo' => 'foo', 'bar' => 'foo', 'id' => 1),
|
||||
(object) array('foo' => 'bar', 'bar' => 'bar', 'id' => 2),
|
||||
);
|
||||
}
|
||||
|
||||
public function getUpper()
|
||||
{
|
||||
return (object) array('id' => 'parent', 'name' => 'a random name');
|
||||
}
|
||||
}
|
||||
|
||||
class ModelToElasticaAutoTransformerTest extends \PHPUnit_Framework_TestCase
|
||||
|
@ -215,4 +228,66 @@ class ModelToElasticaAutoTransformerTest extends \PHPUnit_Framework_TestCase
|
|||
base64_encode(file_get_contents(__DIR__ . '/../fixtures/attachment.odt')), $data['fileContents']
|
||||
);
|
||||
}
|
||||
|
||||
public function testNestedMapping()
|
||||
{
|
||||
$transformer = new ModelToElasticaAutoTransformer();
|
||||
$document = $transformer->transform(new POPO(), array(
|
||||
'sub' => array(
|
||||
'type' => 'nested',
|
||||
'properties' => array('foo' => '~')
|
||||
)
|
||||
));
|
||||
$data = $document->getData();
|
||||
|
||||
$this->assertTrue(array_key_exists('sub', $data));
|
||||
$this->assertInternalType('array', $data['sub']);
|
||||
$this->assertEquals(array(
|
||||
array('foo' => 'foo'),
|
||||
array('foo' => 'bar')
|
||||
), $data['sub']);
|
||||
}
|
||||
|
||||
public function tesObjectMapping()
|
||||
{
|
||||
$transformer = new ModelToElasticaAutoTransformer();
|
||||
$document = $transformer->transform(new POPO(), array(
|
||||
'sub' => array(
|
||||
'type' => 'object',
|
||||
'properties' => array('bar')
|
||||
)
|
||||
));
|
||||
$data = $document->getData();
|
||||
|
||||
$this->assertTrue(array_key_exists('sub', $data));
|
||||
$this->assertInternalType('array', $data['sub']);
|
||||
$this->assertEquals(array(
|
||||
array('bar' => 'foo'),
|
||||
array('bar' => 'bar')
|
||||
), $data['sub']);
|
||||
}
|
||||
|
||||
public function testParentMapping()
|
||||
{
|
||||
$transformer = new ModelToElasticaAutoTransformer();
|
||||
$document = $transformer->transform(new POPO(), array(
|
||||
'upper' => array(
|
||||
'_parent' => array('type' => 'upper', 'identifier' => 'id'),
|
||||
)
|
||||
));
|
||||
|
||||
$this->assertEquals("parent", $document->getParent());
|
||||
}
|
||||
|
||||
public function testParentMappingWithCustomIdentifier()
|
||||
{
|
||||
$transformer = new ModelToElasticaAutoTransformer();
|
||||
$document = $transformer->transform(new POPO(), array(
|
||||
'upper' => array(
|
||||
'_parent' => array('type' => 'upper', 'identifier' => 'name'),
|
||||
)
|
||||
));
|
||||
|
||||
$this->assertEquals("a random name", $document->getParent());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,17 @@ class ModelToElasticaAutoTransformer implements ModelToElasticaTransformerInterf
|
|||
$document = new \Elastica_Document($identifier);
|
||||
foreach ($fields as $key => $mapping) {
|
||||
$property = new PropertyPath($key);
|
||||
if (isset($mapping['type']) && $mapping['type'] == 'attachment') {
|
||||
if (!empty($mapping['_parent']) && $mapping['_parent'] !== '~') {
|
||||
$parent = $property->getValue($object);
|
||||
$identifierProperty = new PropertyPath($mapping['_parent']['identifier']);
|
||||
$document->setParent($identifierProperty->getValue($parent));
|
||||
} else if (isset($mapping['type']) && in_array($mapping['type'], array('nested', 'object'))) {
|
||||
$submapping = $mapping['properties'];
|
||||
$subcollection = $property->getValue($object);
|
||||
$document->add($key, $this->transformNested($subcollection, $submapping, $document));
|
||||
} else if (isset($mapping['type']) && $mapping['type'] == 'multi_field') {
|
||||
throw new \Exception('Please implement me !');
|
||||
} else if (isset($mapping['type']) && $mapping['type'] == 'attachment') {
|
||||
$attachment = $property->getValue($object);
|
||||
if ($attachment instanceof \SplFileInfo) {
|
||||
$document->addFile($key, $attachment->getPathName());
|
||||
|
@ -59,6 +69,25 @@ class ModelToElasticaAutoTransformer implements ModelToElasticaTransformerInterf
|
|||
return $document;
|
||||
}
|
||||
|
||||
/**
|
||||
* transform a nested document or an object property into an array of ElasticaDocument
|
||||
*
|
||||
* @param array $objects the object to convert
|
||||
* @param array $fields the keys we want to have in the returned array
|
||||
* @param Elastica_Document $parent the parent document
|
||||
* @return array
|
||||
*/
|
||||
protected function transformNested($objects, array $fields, $parent)
|
||||
{
|
||||
$documents = array();
|
||||
foreach($objects as $object) {
|
||||
$document = $this->transform($object, $fields);
|
||||
$documents[] = $document->getData();
|
||||
}
|
||||
|
||||
return $documents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to convert any type to a string or an array of strings
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue