我使用fos:elastica处理Symfony2项目。用户可以喜欢和关注他们喜欢的地方。默认情况下,当用户喜欢某个地方时,我们会自动添加"以下"行动。
首先,我将这两个动作保存在数据库中(doctrine2)。我的数据正确保存在db中。
当我使用索引" user_action"进行ES查询时我得到了与某个地方相关的所有行动(以前喜欢和以下)。
但是当我对索引做同样的事情"放置"我只得到第一个动作(如)。
似乎ES无法在建议对象中更新userAction。
另一方面,如果我删除了一个"跟随"动作(在类似之后自动添加)并且我进行第二次调用(通过api)我的动作保存在db中并且还在位置对象中更新。
希望有人能理解我所说的和我尝试做的事^^
place:
mappings:
id:
type: integer
userAction:
type: nested
properties:
userId:
type: integer
userActionTypeId:
type: integer
userActionType:
type: nested
properties:
name:
type: string
user_action:
mappings:
userId:
type: integer
placeId: ~
place:
type: nested
properties:
id:
type: integer
userActionType:
type: nested
properties:
name: ~
`fos_elastica.listener.place.user_action`:
class: API\Rest\v1\PlaceBundle\EventListener\ElasticaUserActionListener
arguments:
- @fos_elastica.object_persister.search.user_action
- ['postPersist', 'postRemove']
- @fos_elastica.indexable
calls:
- [ setContainer, ['@service_container', @fos_elastica.object_persister.search.place ] ]
tags:
- { name: 'doctrine.event_subscriber' }
<?php
namespace API\Rest\v1\PlaceBundle\EventListener;
use Doctrine\Common\EventArgs;
use FOS\ElasticaBundle\Doctrine\Listener as BaseListener;
use FOS\ElasticaBundle\Persister\ObjectPersister;
use Symfony\Component\DependencyInjection\ContainerInterface;
use API\Rest\v1\UserActionBundle\Entity\UserAction;
class ElasticaUserActionListener extends BaseListener
{
private $container;
private $objectPersisterSuggestion;
public function setContainer(ContainerInterface $container, ObjectPersister $objectPersisterSuggestion)
{
$this->container = $container;
$this->objectPersisterPlace = $objectPersisterPlace;
}
public function postPersist(EventArgs $eventArgs)
{
$entity = $eventArgs->getEntity();
if ($entity instanceof UserAction) {
$this->scheduledForInsertion[] = $entity;
$this->objectPersisterPlace->replaceOne($entity->getPlace());
}
}
public function postRemove(EventArgs $eventArgs)
{
$entity = $eventArgs->getEntity();
if ($entity instanceof UserAction) {
$this->scheduleForDeletion($entity);
$this->objectPersisterPlace->replaceOne($entity->getPlace());
}
}
}
query : http://localhost:9200/search/place/_search
"hits" : [
{
"_index" : "search",
"_type" : "place",
"_id" : "320",
"_score" : 5.7004805,
"_source":{
"userAction":[
{
"userActionType":{
"name":"like"
},
"userActionTypeId":3,
"userId":3
}
]
}
}
]
query : http://localhost:9200/search/user_action/_search
"hits" : [
{
"_index" : "search",
"_type" : "user_action",
"_id" : "50",
"_score" : 5.7004805,
"_source" : {
"userId" : 4,
"placeId" : 320,
"userActionType" : {
"name" : "following"
}
}
},
{
"_index" : "search",
"_type" : "user_action",
"_id" : "49",
"_score" : 5.402646,
"_source" : {
"userId" : 4,
"placeId" : 320,
"userActionType" : {
"name" : "like"
}
}
}
]
我终于找到了正确的方法。我太快就冲了数据。
我替换了这个错误的代码
$em = $this->getEntityManager();
$em->persist($like);
$em->flush();
$em = $this->getEntityManager();
$em->persist($following);
$em->flush();
通过
$em = $this->getEntityManager();
$em->persist($like);
$em->persist($following);
$em->flush();
它正在工作!!!!
希望这可以帮助某人。
答案 0 :(得分:0)
对于我来说,使用FOSElasticaBundle 3.0.x来更新嵌套对象的方法通常如下:
将此添加到app/config/config.yml
services:
# your other services
fos_elastica.listener.search.user_action:
class: "Acme\Bundle\UserActionBundle\EventListener\ElasticaUserActionListener"
arguments:
- @fos_elastica.object_persister.search.user_action
- ['postPersist', 'postInsert', 'postUpdate', 'preRemove']
- @fos_elastica.indexable
- { indexName: 'user_action', typeName: 'userAction'}
calls:
- [ setContainer, ['@service_container', @fos_elastica.object_persister.search.user_action] ]
tags:
- { name: 'doctrine.event_subscriber' }
然后在UserActionBundle\EventListener
中创建一个新文件:
# Acme\Bundle\UserActionBundle\EventListener\ElasticaUserActionListener.php
namespace Acme\Bundle\UserActionBundle\EventListener;
use Doctrine\Common\EventArgs;
use FOS\ElasticaBundle\Doctrine\Listener as BaseListener;
use FOS\ElasticaBundle\Persister\ObjectPersister;
use Symfony\Component\DependencyInjection\ContainerInterface;
class ElasticaUserActionListener extends BaseListener
{
private $container;
private $objectPersisterUserAction;
public function setContainer(ContainerInterface $container, ObjectPersister $objectPersisterUserAction)
{
$this->container = $container;
$this->objectPersisterUserAction = $objectPersisterUserAction;
}
public function getClassAccessorArray() {
return [
[
'accessor' => 'getPlace',
'class' => new Place(),
],
// add more child objects here, if needed
];
}
public function postPersist(EventArgs $args)
{
$entity = $args->getEntity();
foreach ($this->getClassAccessorArray() as $accessorArray) {
$class = $accessorArray['class'];
$accessorFunction = $accessorArray['accessor'];
if ($entity instanceof $class) {
$this->scheduledForInsertion[] = $entity;
$this->objectPersisterUserAction->insertOne($entity->$accessorFunction());
break;
}
}
}
public function postUpdate(EventArgs $args)
{
$entity = $args->getEntity();
foreach ($this->getClassAccessorArray() as $accessorArray) {
$class = $accessorArray['class'];
$accessorFunction = $accessorArray['accessor'];
if ($entity instanceof $class) {
$this->scheduledForUpdate[] = $entity;
$this->objectPersisterUserAction->replaceOne($entity->$accessorFunction());
break;
}
}
}
public function preRemove(EventArgs $eventArgs) {
$entity = $eventArgs->getEntity();
foreach ($this->getClassAccessorArray() as $accessorArray) {
$class = $accessorArray['class'];
$accessorFunction = $accessorArray['accessor'];
if ($entity instanceof $class) {
$this->scheduleForDeletion($entity);
$this->objectPersisterUserAction->deleteOne($entity->$accessorFunction());
}
}
}
}
这可以在直接更新嵌套对象时更新ElasticSearch的索引。在您的情况下,因为您实际上在Place
和UserAction
之间存在双向关系,您可以扩展Listener类来处理这两个类,或者只是复制并创建ElasticaPlaceListener
服务和班级。