2013-03-15 13 views
12

Chciałbym móc dopasować wyszukiwanie wielu słów do wielu pól, gdzie każde wyszukane słowo jest zawarte w dowolnych pól, dowolnej kombinacji. Połów jest chciałbym unikać używania query_string.Multi-field, multi-word, match bez query_string

curl -X POST "http://localhost:9200/index/document/1" -d '{"id":1,"firstname":"john","middlename":"clark","lastname":"smith"}' 
curl -X POST "http://localhost:9200/index/document/2" -d '{"id":2,"firstname":"john","middlename":"paladini","lastname":"miranda"}' 

Chciałbym poszukiwania „John Smith”, aby dopasować tylko dokument 1. Następujące zapytanie robi to, co muszę, ale wolałbym unikać query_string w przypadku, gdy użytkownik przechodzi „lub”, „I” i którykolwiek z innych zaawansowanych parametrów.

curl -X GET 'http://localhost:9200/index/_search?per_page=10&pretty' -d '{ 
    "query": { 
    "query_string": { 
     "query": "john smith", 
     "default_operator": "AND", 
     "fields": [ 
     "firstname", 
     "lastname", 
     "middlename" 
     ] 
    } 
    } 
}' 
+0

Ciągle przychodzę do tego pytania w kółko. Świetne, wiecznie zielone pytanie! –

Odpowiedz

23

To, czego szukasz, to multi-match query, ale nie działa tak, jak byś chciał.

Porównaj wyjście validate dla multi_match i query_string.

multi_match (z operatorem and) będzie upewnić się, że wszystkie terminy występują w co najmniej jednej dziedzinie:

curl -XGET 'http://127.0.0.1:9200/_validate/query?pretty=1&explain=true' -d ' 
{ 
    "multi_match" : { 
     "operator" : "and", 
     "fields" : [ 
     "firstname", 
     "lastname" 
     ], 
     "query" : "john smith" 
    } 
} 
' 

# { 
# "_shards" : { 
#  "failed" : 0, 
#  "successful" : 1, 
#  "total" : 1 
# }, 
# "explanations" : [ 
#  { 
#   "index" : "test", 
#   "explanation" : "((+lastname:john +lastname:smith) | (+firstname:john +firstname:smith))", 
#   "valid" : true 
#  } 
# ], 
# "valid" : true 
# } 

Podczas query_string (z default_operator AND) sprawdzi, że każdy termin występuje w co najmniej jednej dziedzinie:

curl -XGET 'http://127.0.0.1:9200/_validate/query?pretty=1&explain=true' -d ' 
{ 
    "query_string" : { 
     "fields" : [ 
     "firstname", 
     "lastname" 
     ], 
     "query" : "john smith", 
     "default_operator" : "AND" 
    } 
} 
' 

# { 
# "_shards" : { 
#  "failed" : 0, 
#  "successful" : 1, 
#  "total" : 1 
# }, 
# "explanations" : [ 
#  { 
#   "index" : "test", 
#   "explanation" : "+(firstname:john | lastname:john) +(firstname:smith | lastname:smith)", 
#   "valid" : true 
#  } 
# ], 
# "valid" : true 
# } 

więc masz kilka opcji, aby osiągnąć to, czego po:

  1. Preparse terminy wyszukiwania, aby usunąć rzeczy jak symboli wieloznacznych, itp, przed użyciem query_string

  2. Preparse warunki wyszukiwania, aby wyodrębnić każde słowo, a następnie wygenerować multi_match zapytania za słowem

  3. Korzystanie index_name w twojej mapowanie pól nazw w celu indeksowania ich danych w jednym polu, które następnie można wykorzystać do wyszukiwania. (Podobnie jak swój własny all dziedzinie):

W następujący sposób:

curl -XPUT 'http://127.0.0.1:9200/test/?pretty=1' -d ' 
{ 
    "mappings" : { 
     "test" : { 
     "properties" : { 
      "firstname" : { 
       "index_name" : "name", 
       "type" : "string" 
      }, 
      "lastname" : { 
       "index_name" : "name", 
       "type" : "string" 
      } 
     } 
     } 
    } 
} 
' 

curl -XPOST 'http://127.0.0.1:9200/test/test?pretty=1' -d ' 
{ 
    "firstname" : "john", 
    "lastname" : "smith" 
} 
' 

curl -XGET 'http://127.0.0.1:9200/test/test/_search?pretty=1' -d ' 
{ 
    "query" : { 
     "match" : { 
     "name" : { 
      "operator" : "and", 
      "query" : "john smith" 
     } 
     } 
    } 
} 
' 

# { 
# "hits" : { 
#  "hits" : [ 
#   { 
#    "_source" : { 
#    "firstname" : "john", 
#    "lastname" : "smith" 
#    }, 
#    "_score" : 0.2712221, 
#    "_index" : "test", 
#    "_id" : "VJFU_RWbRNaeHF9wNM8fRA", 
#    "_type" : "test" 
#   } 
#  ], 
#  "max_score" : 0.2712221, 
#  "total" : 1 
# }, 
# "timed_out" : false, 
# "_shards" : { 
#  "failed" : 0, 
#  "successful" : 5, 
#  "total" : 5 
# }, 
# "took" : 33 
# } 

Uwaga jednak, że firstname i lastname już przeszukiwać niezależnie. Dane dla obu pól zostały zindeksowane na name.

Można użyć multi-fields z parametrem path aby je przeszukiwać zarówno samodzielnie i razem, w następujący sposób:

curl -XPUT 'http://127.0.0.1:9200/test/?pretty=1' -d ' 
{ 
    "mappings" : { 
     "test" : { 
     "properties" : { 
      "firstname" : { 
       "fields" : { 
        "firstname" : { 
        "type" : "string" 
        }, 
        "any_name" : { 
        "type" : "string" 
        } 
       }, 
       "path" : "just_name", 
       "type" : "multi_field" 
      }, 
      "lastname" : { 
       "fields" : { 
        "any_name" : { 
        "type" : "string" 
        }, 
        "lastname" : { 
        "type" : "string" 
        } 
       }, 
       "path" : "just_name", 
       "type" : "multi_field" 
      } 
     } 
     } 
    } 
} 
' 

curl -XPOST 'http://127.0.0.1:9200/test/test?pretty=1' -d ' 
{ 
    "firstname" : "john", 
    "lastname" : "smith" 
} 
' 

Przeszukiwanie pole any_name działa:

curl -XGET 'http://127.0.0.1:9200/test/test/_search?pretty=1' -d ' 
{ 
    "query" : { 
     "match" : { 
     "any_name" : { 
      "operator" : "and", 
      "query" : "john smith" 
     } 
     } 
    } 
} 
' 

# { 
# "hits" : { 
#  "hits" : [ 
#   { 
#    "_source" : { 
#    "firstname" : "john", 
#    "lastname" : "smith" 
#    }, 
#    "_score" : 0.2712221, 
#    "_index" : "test", 
#    "_id" : "Xf9qqKt0TpCuyLWioNh-iQ", 
#    "_type" : "test" 
#   } 
#  ], 
#  "max_score" : 0.2712221, 
#  "total" : 1 
# }, 
# "timed_out" : false, 
# "_shards" : { 
#  "failed" : 0, 
#  "successful" : 5, 
#  "total" : 5 
# }, 
# "took" : 11 
# } 

wyszukiwania firstname dla john AND smith robi” t pracy:

curl -XGET 'http://127.0.0.1:9200/test/test/_search?pretty=1' -d ' 
{ 
    "query" : { 
     "match" : { 
     "firstname" : { 
      "operator" : "and", 
      "query" : "john smith" 
     } 
     } 
    } 
} 
' 

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

Ale szukając firstname tylko dla john działa poprawnie:

curl -XGET 'http://127.0.0.1:9200/test/test/_search?pretty=1' -d ' 
{ 
    "query" : { 
     "match" : { 
     "firstname" : { 
      "operator" : "and", 
      "query" : "john" 
     } 
     } 
    } 
} 
' 

# { 
# "hits" : { 
#  "hits" : [ 
#   { 
#    "_source" : { 
#    "firstname" : "john", 
#    "lastname" : "smith" 
#    }, 
#    "_score" : 0.30685282, 
#    "_index" : "test", 
#    "_id" : "Xf9qqKt0TpCuyLWioNh-iQ", 
#    "_type" : "test" 
#   } 
#  ], 
#  "max_score" : 0.30685282, 
#  "total" : 1 
# }, 
# "timed_out" : false, 
# "_shards" : { 
#  "failed" : 0, 
#  "successful" : 5, 
#  "total" : 5 
# }, 
# "took" : 3 
# } 
0

myślę „mecz” zapytania jest to, czego szukasz.

„Mecz rodzinnym zapytań nie przechodzą«query parsowanie»procesu To nie obsługuje nazwa pola prefiksów, asterisk znaków lub innych funkcji "z góry", dlatego szanse na jego zawieszenie są bardzo małe/nieistniejące i zapewnia doskonałe zachowanie, jeśli chodzi o analizę i uruchamianie tego tekstu jako zachowania zapytania (co zwykle jest pole wyszukiwania tekstu nie) "

http://www.elasticsearch.org/guide/reference/query-dsl/match-query.html

Powiązane problemy