ElasticSearch: странное поведение поиска при использовании анализатора снежного кома

Допустим, у меня есть индекс ElasticSearch, определенный следующим образом:

curl -XPUT 'http://localhost:9200/test' -d '{
  "mappings": {
    "example": {
      "properties": {
        "text": {
          "type": "string",
          "analyzer": "snowball"
        }
      }
    }
  }
}'

curl -XPUT 'http://localhost:9200/test/example/1' -d '{
  "text": "foo bar organization"
}'

Когда я ищу "fooorganizations" с помощью анализатора снежного кома, оба ключевых слова совпадают, как и ожидалось:

curl -XGET http://localhost:9200/test/example/_search -d '{
  "query": {
    "text": {
      "_all": {
        "query": "foo organizations",
        "analyzer": "snowball"
      }
    }
  },
  "highlight": {
    "fields": {
      "text": {}
    }
  }
}'

{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 0.015912745,
    "hits": [
      {
        "_index": "test",
        "_type": "example",
        "_id": "1",
        "_score": 0.015912745,
        "_source": {
          "text": "foo bar organization"
        },
        "highlight": {
          "text": [
            "<em>foo</em> bar <em>organization</em>"
          ]
        }
      }
    ]
  }
}

Но когда я ищу только «организации», я вообще не получаю никакого результата, что очень странно:

curl -XGET http://localhost:9200/test/example/_search -d '{
  "query": {
    "text": {
      "_all": {
        "query": "organizations",
        "analyzer": "snowball"
      }
    }
  },
  "highlight": {
    "fields": {
      "text": {}
    }
  }
}'

{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 0,
    "max_score": null,
    "hits": []
  }
}

Однако, если я ищу «бары», он все равно попадает:

curl -XGET http://localhost:9200/test/example/_search -d '{
  "query": {
    "text": {
      "_all": {
        "query": "bars",
        "analyzer": "snowball"
      }
    }
  },
  "highlight": {
    "fields": {
      "text": {}
    }
  }
}'

{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 0.10848885,
    "hits": [
      {
        "_index": "test",
        "_type": "example",
        "_id": "1",
        "_score": 0.10848885,
        "_source": {
          "text": "foo bar organization"
        },
        "highlight": {
          "text": [
            "foo <em>bar</em> organization"
          ]
        }
      }
    ]
  }
}

Я предполагаю, что разница между «баром» и «организацией» заключается в том, что «организация» связана с «органом», а «бар» связана с самой собой. Но как мне добиться правильного поведения, чтобы 2-й поиск срабатывал?


person tycooon    schedule 14.03.2012    source источник


Ответы (2)


Текст "организация foo bar" индексируется дважды - в поле текст и в поле _all. Поле текст использует анализатор снежного кома, а поле _all использует стандартный анализатор. Поэтому после анализа тестовой записи поле _all содержит токены: "foo", "bar" и "organization". При поиске указанный анализатор Snowball преобразует "foo" в "foo", "bars" в "bar" и "organization" в "organ". Итак, слова «foo» и «bars» в запросе соответствуют тестовой записи, а термин «organization» — нет. Выделение выполняется по полям независимо от поиска, поэтому в первом результате выделяется слово «организация».

person imotov    schedule 14.03.2012
comment
Это имеет смысл, спасибо. Есть ли способ посмотреть на фактические токены, которые есть в моем индексе? И могу ли я указать ES использовать снежный ком для столбца _all? - person tycooon; 15.03.2012
comment
Не существует простого способа взглянуть на фактические токены в индексе, но можно увидеть, как текст анализируется с помощью Analyze API (elasticsearch.org/guide/reference/api/). Вы можете установить анализатор снежного кома для поля _all во время создания индекса gist.github.com/2043721 . Кроме того, Snowball можно установить в качестве анализатора по умолчанию для всех полей gist.github.com/2043697. - person imotov; 15.03.2012

Лучше использовать анализатор во время индексации, чем во время поиска. Сопоставьте текстовое поле с анализатором снежного кома, а затем проиндексируйте. Это создаст несколько токенов для организации, в которую входят организации. Это работает для меня.

person harsha    schedule 06.03.2014