Как использовать ElasticSearch, чтобы предлагать (результаты) города по мере ввода

Я новичок в Elasticsearch, и я потратил несколько часов, пытаясь решить эту проблему, поэтому заранее спасибо, если вы попытаетесь мне помочь.

:) (Не слишком) Краткое пояснение: (Что у меня есть на данный момент и чего я пытаюсь достичь):

Я создал базу данных CouchDB (spain_locales), которая содержит более 8000 документов с испанскими городами и провинциями. С другой стороны, у меня есть HTML-форма с автозаполнением jQuery, и я показываю результаты по мере ввода. Я подключаюсь к ElasticSearch из созданного мной PHP (поставщика услуг Laravel) и возвращаю результаты для автозаполнения jQuery. Я предполагаю, что это можно сделать, подключившись с клиента напрямую к ElasticSearch, но из соображений безопасности я пока предпочитаю, чтобы это было так.

:( Проблема:

Результаты, которые я получаю от ElasticSearch, не совсем то, что я ожидаю, и я не знаю, как исправить то, что у меня есть, и правильно ли это сделать. Я не знаю, нужен ли логический запрос для того, что мне нужно, или мне следует использовать другой тип запроса.

  1. Я получаю результаты только в том случае, если я набираю слова точно так же, как они есть в базе данных:

    Если я набираю Алава, я получаю результаты, но НЕ для Алава (имеет значение акцент Á)

  2. Я не получаю результатов, пока не наберу полное слово:

    Если я наберу Albacete, я получу результаты, но НЕ для Albacet.

Я использовал плагин CouchDB River для ElasticSearch для синхронизации CouchDB с ElasticSearch ›› https://github.com/elasticsearch/elasticsearch-river-couchdb, и я сделал это с помощью следующей команды через терминал:

curl -XPUT 'localhost:9200/_river/spain_locales/_meta' -d '{
    "type" : "couchdb",
    "couchdb" : {
        "host" : "localhost",
        "port" : 5984,
        "db" : "spain_locales",
        "filter" : null
    },
    "index" : {
        "index" : "spain_locales",
        "type" : "spain_locales",
        "bulk_size" : "100",
        "bulk_timeout" : "10ms"
    }
}'

Я также пробовал с:

curl -XPUT 'localhost:9200/_river/spain_locales/_meta' -d '{
    "type" : "couchdb",
    "couchdb" : {
        "host" : "localhost",
        "port" : 5984,
        "db" : "spain_locales",
        "filter" : null
    },
    "index" : {
        "number_of_shards" : 2,
        "refresh_interval" : "1s",
        "analysis": {
          "analyzer": {
            "folding": {
              "tokenizer": "standard",
              "filter":  [ "lowercase", "asciifolding" ]
            }
          }
        },
        "index" : "spain_locales",
        "type" : "spain_locales",
        "bulk_size" : "100",
        "bulk_timeout" : "10ms"
    }
}'

Ни одно из вышеперечисленных не возвращает никаких ошибок и успешно не создает синхронизацию _river, но по-прежнему имеет проблемы с акцентами и целыми словами.

Я также попытался каким-то образом применить необходимые фильтры с помощью следующей команды через терминал:

curl -XPUT 'localhost:9200/spain_locales/' -d '
{
  "settings": {
    "analysis": {
      "analyzer": {
        "folding": {
          "tokenizer": "standard",
          "filter":  [ "lowercase", "asciifolding" ]
        }
      }
    }
  },
  "uuid":"KwKrBc3uQoG5Ld1nOdc5rQ"
}'

Но я получаю следующую ошибку:

{"error":"IndexAlreadyExistsException[[spain_locales] already exists]","status":400}

Примеры документов CouchDB:

{
   "_id": "1",
   "_rev": "1-087ddbe8593f68f1d7d37a9c3f6de787",
   "Provincia": "Álava",
   "Poblacion": "Alegría-Dulantzi",
   "helper": ""
}

{
   "_id": "10",
   "_rev": "1-ce38dcdabeb3b34d34d2296c6e2fdf24",
   "Provincia": "Álava",
   "Poblacion": "Ayala/Aiara",
   "helper": ""
}

{
   "_id": "100",
   "_rev": "1-72e66601e378ee48519aa93601dc0717",
   "Provincia": "Albacete",
   "Poblacion": "Herrera (La)",
   "helper": "La Herrera"
}

Поставщик/контроллер услуг PHP:

public function searchzones(){

    $q = (Input::has('term')) ? Input::get('term') : 'null';

    $params['index'] = 'spain_locales';
    $params['type']  = 'spain_locales';

    $params['body']['query']['bool']['should'] = array(
        array('match' => array('Poblacion' =>  $q)),
        array('match' => array('Provincia' =>  $q))
    );

    $query = $this->elasticsearch->search($params);

    if ($query['hits']['total'] >= 1){

        $results = $query['hits']['hits'];

        foreach ($results as $zone) {
            
            $databag[] = array( "value"     => $zone['_source']['Poblacion'].', '.$zone['_source']['Provincia'],
                                "state"     => $zone['_source']['Provincia'],
                                "city"      => $zone['_source']['Poblacion'],
            );

        }

    } else {

        $results = ['res' => null];
        $databag[] = array();

    }

    return $databag;

    } // End Search Zones

jQuery (JavaScript):

// Sugest locations when user type in zones 
$(document).ready(function() {
    $('#zones').autocomplete({
            
            source : applink + 'ajax/searchzones',
            select : function(event, ui){
                console.log(ui);
            }
                
    }); // End autocomplete
}); // End Document ready

Часть HTML-формы (Twitter Bootstrap):

<div class="form-group">
<div class="input-group input-append dropdown">
<input type="text" class="form-control typeahead" placeholder="City name" name="zones" id="zones">
<div class="input-group-btn" >
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></button>
<ul class="dropdown-menu dropdown-menu-right" id="dropZonesAjax">                           
</ul>
</div>
</div>
<div id="zonesAjax"></div>   
</div>

Я нашел следующий ресурс: http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/asciifolding-token-filter.html, но я не знаю, как это реализовать/достичь.

Большое спасибо за ваше время и за попытку помочь! Извините за мой английский!


person vitaminasweb    schedule 11.12.2014    source источник
comment
Можете ли вы опубликовать сопоставление, которое вы используете для этого индекса? Кроме того, ознакомьтесь с документацией по предложению завершения (elasticsearch.org/guide/en/elasticsearch/reference/current/)?   -  person hubbardr    schedule 12.12.2014
comment
Привет! Спасибо за ответ! Я не знаю, что вы имеете в виду под картографией. Я больше ничего не делал с elasticsearc ... Только то, что я объяснил.   -  person vitaminasweb    schedule 12.12.2014


Ответы (1)


Попробуйте создать сопоставление перед индексацией. Затем вы можете определить упомянутый вами анализатор (свертывание) и назначить его своим полям:

{
  "settings": {
    "analysis": {
      "analyzer": {
        "folding": {
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "asciifolding"
          ]
        }
      }
    }
  },
  "mappings": {
    "locales": {
      "properties": {
        "Provincia": {
          "type": "string",
          "analyzer": "folding"
        },
        "Poblacion": {
          "type": "string",
          "analyzer": "folding"
        },
        "helper": {
          "type": "string"
        }
      }
    }
  }
}
person sven.kwiotek    schedule 12.12.2014