FOS эластик вложенный фильтр не работает

Я изо всех сил пытаюсь заставить мой вложенный фильтр работать с тегами,

У меня есть личность лица, и вот его отображение из

http://localhost:9200/search/person/_mapping
{
  "search": {
    "mappings": {
      "person": {
        "_meta": {
          "model": "Foo\\CoreBundle\\Entity\\Person"
        },
        "properties": {
          "adresses": {
            "type": "nested",
            "properties": {
              "city": {
                "type": "string",
                "store": true
              }
            }
          },
          "certified": {
            "type": "string",
            "store": true
          },
          "completeness": {
            "type": "string",
            "store": true
          },
          "fullname": {
            "type": "string",
            "store": true
          },
          "lastName": {
            "type": "string",
            "store": true
          },
          "name": {
            "type": "string",
            "store": true
          },
          "source": {
            "type": "string",
            "store": true
          },
          "tags": {
            "type": "nested",
            "properties": {
              "name": {
                "type": "string",
                "store": true
              }
            }
          },
          "type": {
            "type": "string",
            "store": true
          }
        }
      }
    }
  }
}

данные, кажется, заполнены правильно, есть лицо лица со следующими тегами

{
  "people": [
    {
      "id": 13355,
      "created_at": "2014-12-27T09:30:54+0100",
      "updated_at": "2014-12-27T09:30:54+0100",
      "name": "Vorname",
      "last_name": "nachname",
      "ms": "Anrede",
      "title": "Titel",
      "source": "Quelle",
      "description": "info",
      "email": "email",
      "language": "EN",
      "status": "unready",
      "links": [
        "link"
      ],
      "tags": [
        {
          "id": 4176,
          "created_at": "2014-12-27T09:30:54+0100",
          "updated_at": "2014-12-27T09:30:54+0100",
          "name": "position",
          "type": "function"
        },
        {
          "id": 4177,
          "created_at": "2014-12-27T09:30:54+0100",
          "updated_at": "2014-12-27T09:30:54+0100",
          "name": "kategorie",
          "type": "category"
        }
      ],
      "type": "kategorie",
      "slug": "vorname_nachname",
      "certified": "certified"
    }
  ]
}

Вы видите, что есть два тега с именами "позиция" и "категория"

вот мой код, мой базовый запрос - это подстановочный знак для свойства полного имени, который отлично работает

$finder = $this->container->get('fos_elastica.finder.search.person');
$query = new \Elastica\Query();
$baseQuery=new \Elastica\Query\Wildcard();
$baseQuery->setValue("fullname", "*".trim(mb_strtolower($term))."*", $boost = 1.0);

$nestedFilter = new \Elastica\Filter\Nested();
$termFilter = new \Elastica\Filter\Term();
$termFilter->setTerm("name","position");
$nestedFilter->setPath("tags");
$nestedFilter->setFilter($termFilter);
$baseQuery = new \Elastica\Query\Filtered($baseQuery, $nestedFilter);        
$query->setQuery($baseQuery);
$people = $finder->find($query);

вот результирующий запрос:

elastica.INFO: search/person/_search (GET) 3.30 ms 
{
  "query": {
    "filtered": {
      "query": {
        "wildcard": {
          "fullname": {
            "value": "**",
            "boost": 1
          }
        }
      },
      "filter": {
        "nested": {
          "path": "tags",
          "filter": {
            "term": {
              "name": "position"
            }
          }
        }
      }
    }
  },
  "size": "10",
  "from": 0
}

но нет результатов, если я пропущу вложенный термин фильтр, он работает

Есть идеи, что я делаю не так? вот мое отображение orm:

/**
 * @ORM\ManyToMany(targetEntity="Foo\CoreBundle\Entity\Tag", inversedBy="tags")
 * @ORM\JoinTable(name="person_has_tags")
 **/
 private $tags;

1 ответ

Решение

Так что я сам столкнулся с этой проблемой несколько месяцев назад. Короче говоря, индекс эластичного поиска разбивает имя вашего тега, поэтому "позиция" больше не имеет точного соответствия. То, что упругий поиск имеет в своем индексе, на самом деле является чем-то ближе к "pos", "it" и "tion ". Вам нужно либо дать упругому поиску знать, чтобы разбить это поле, когда вы передаете объект для индексации, либо вы просто ищете по идентификатору вашего тега, а не по имени. В итоге я выбрал маршрут id, потому что он мне показался более эффективным.

вот мой код в качестве примера, обратите внимание, что я вложил свой вложенный фильтр в фильтр bool, потому что у меня есть другие параметры поиска, которые я здесь не показываю:

$query = new Query\QueryString('*' . $searchText .'*');
$boolFilter = new Bool();
$nestedFilter = new Nested();
$nestedFilter->setPath('categories');
$categoryFilter = new Term(['id' => $categoryId]);
$nestedFilter->setFilter($categoryFilter);
$boolFilter->addMust($nestedFilter);
$filteredQuery = new Filtered($query, $boolFilter);

и фрагмент моего упругого объекта:

"name": "Sample Object",
"published": true
"categories": [
    {
        "id": 1,
        "name": "cool"
    },
    {
        "id": 3,
        "name": "awesome"
    }
]
Другие вопросы по тегам