2016-08-03 4 views
0

Я не могу понять, как искать слова со специальными символами.ElasticSearch и специальные символы

К примеру, у меня есть два документа:

1) Мы ищем C++ и разработчики C#
2) Мы ищем разработчиков C

Я хочу только, чтобы найти документ, содержащий C++ ,

Код для создания индекса, документов и поиска:

from elasticsearch import Elasticsearch 
from elasticsearch.helpers import scan 

ELASTIC_SEARCH_NODES = ['http://localhost:9200'] 

INDEX = 'my_index' 
DOC_TYPE = 'material' 


def create_index(): 
    data = { 
     "settings": { 
      "analysis": { 
      "analyzer": { 
       "my_analyzer": { 
        "type": "custom", 
        "filter": [ 
         "lowercase" 
        ], 
        "tokenizer": "whitespace", 
       } 
      } 
      } 
     } 
    } 

    print es_client.indices.create(index=INDEX, body=data) 


def create_doc(body): 

    if es_client.exists(INDEX, DOC_TYPE, body['docid']): 
     es_client.delete(INDEX, DOC_TYPE, body['docid']) 

    print es_client.create(index=INDEX, doc_type=DOC_TYPE, body=body, id=body['docid']) 


def find_doc(value): 
    results_generator = scan(es_client, 
      query={"query": { 

        "match_phrase" : { 
         "text" : value 
        } 

      }}, 
      index=INDEX 
     ) 
    return results_generator 


if __name__ == '__main__': 
    es_client = Elasticsearch(ELASTIC_SEARCH_NODES, verify_certs=True) 

    # create_index() 
    doc1 = {"docid": 1, 'text': u"We are looking for C developers"} 
    doc2 = {"docid": 2, 'text': u"We are looking for C++ and C# developers"} 

    # create_doc(doc1) 
    # create_doc(doc2) 

    for r in find_doc("C++"): 
     print r 

Результат поиска (если я escape+ ("C\+\+"), то результат будет таким же):

{u'_score': 0.0, u'_type': u'material', u'_id': u'2', u'_source': {u'text': u'We are looking for C++ and C# developers', u'docid': 2}, u'_index': u'my_index'} 
{u'_score': 0.0, u'_type': u'material', u'_id': u'1', u'_source': {u'text': u'We are looking for C developers', u'docid': 1}, u'_index': u'my_index'} 

Кажется, что такой результат получается потому, что при делении на символы токенов, как + и #not indexed, и по сути, он ищет документы, в которых есть символ C:

curl 'http://localhost:9200/my_index/material/_search?pretty=true' -d '{ 
    "query" : { 
     "match_all" : { } 
    }, 
    "script_fields": { 
     "terms" : { 
      "script": "doc[field].values", 
      "params": { 
       "field": "text" 
      } 
     } 
    } 
}' 

Результат:

{ 
    "took" : 3, 
    "timed_out" : false, 
    "_shards" : { 
    "total" : 5, 
    "successful" : 5, 
    "failed" : 0 
    }, 
    "hits" : { 
    "total" : 2, 
    "max_score" : 1.0, 
    "hits" : [ { 
     "_index" : "my_index", 
     "_type" : "material", 
     "_id" : "2", 
     "_score" : 1.0, 
     "fields" : { 
     "terms" : [ "and", "are", "c", "developers", "for", "looking", "we" ] 
     } 
    }, { 
     "_index" : "my_index", 
     "_type" : "material", 
     "_id" : "1", 
     "_score" : 1.0, 
     "fields" : { 
     "terms" : [ "are", "c", "developers", "for", "looking", "we" ] 
     } 
    }] 
    } 
} 

Как эта проблема может быть решена? Второй вопрос, связанный с предыдущим: можно ли искать только не буквенно-цифровые символы, такие как % или +?

P.S. Я использую Elastic 2.3.2 и elasticsearch = 2.3.0.

+0

Я имею в виду, это очевидно, да, оно было проиндексировано таким образом, чтобы опустить ++ и #, и, конечно же, позже вы сможете найти их обоих. Я не уверен, получаю ли я весь код python, но похоже, что вы не настроили ваш анализатор для работы с вашим полем – Mysterion

ответ

0

Спасибо Andrew, я решил проблему. Проблема заключалась в том, что для индексации использовался стандартный анализатор, а не my_analyzer. Таким образом, я забыл использовать отображение. Правильный вариант:

data = { 
    "settings": { 
     "analysis": { 
     "analyzer": { 
      "my_analyzer": { 
       "type": "custom", 
       "filter": [ 
        "lowercase" 
       ], 
       "tokenizer": "whitespace", 
      } 
     } 
     } 
    }, 
    "mappings": { 
     "material": { 
      "properties": { 
       "docid": { 
        "type": "integer" 
       }, 
       "text": { 
        "type": "string", 
        "analyzer": "my_analyzer" 
       } 
      } 
     } 
    } 
} 

Кроме того, необходимо было воссоздать индекс и добавить документы. Для поиска специальных символов, я использую query_string. Код find_doc функции:

def find_doc(value): 
    results_generator = scan(es_client, 
      query= 
      { 
       "query": { 
        "filtered" : { 
         "query" : { 
          "query_string" : { 
           "query": value, 
           "fields" : ["text"], 
           "analyzer": ANALYZER, 
           "default_operator": "AND" 
          }, 

         } 
        } 

       } 
      }, 
      index=INDEX 
     ) 
    return results_generator 

Примеры запросов (теперь wildcard-characters могут быть использованы):

for r in find_doc("*#"): 
    print r 

for r in find_doc(u"%"): 
    print r 

for r in find_doc("looking fo*"): 
    print r 

Запрос на проверку анализатора (на котором маркер строка разбивается):

curl -XPOST "http://localhost:9200/my_index/_analyze?analyzer=my_analyzer&pretty=true" -d 'We are looking for C++ and C# developers' 
Смежные вопросы