简体   繁体   中英

FOS elastica nested filter not working

I'm struggling get my nested filter for tags to work,

I have a person entity and here is its mapping from

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
          }
        }
      }
    }
  }
}

the data seems to be populated correct, there is a person entity with following tags

{
  "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"
    }
  ]
}

you see there are two tags with names "position" and "kategorie"

here is my code, my basequery is a wildcard on fullname property which works perfect

$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);

here's the resulting 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
}

but there are no results, if I leave out the nested term filter it works

any idea what I'm doing wrong? here's my orm-mapping:

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

So I actually ran into this problem myself a few months ago. Long story short, the elastic search index is breaking up the name of your tag so "position" no longer has an exact match. What elastic search has in it's index is actually something closer to "pos", "it", and "tion" You either need to let elastic search know to know break up that field when you hand the object over for indexing or you just search by the id of your tag rather than by the name. I ended up taking the id route because it seemed more efficient to me.

here is my code as an example, note that i embed my nested filter into a bool filter because i have other search parameters that i'm not showing here:

$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);

and a snippet of my elastic object:

"name": "Sample Object",
"published": true
"categories": [
    {
        "id": 1,
        "name": "cool"
    },
    {
        "id": 3,
        "name": "awesome"
    }
]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM