2015-01-05 4 views
1

У меня есть это отображение:elasticsearch вложенного обратного фильтр пустого результата

"post": { 
    "model": "Post", 
    "properties": { 
     "id": { 
     "type": "integer" 
     }, 
     "title": { 
     "type": "string", 
     "analyzer": "custom_analyzer", 
     "boost": 5 
     }, 
     "description": { 
     "type": "string", 
     "analyzer": "custom_analyzer", 
     "boost": 4 
     }, 
     "condition": { 
     "type": "integer", 
     "index": "not_analyzed" 
     }, 
     "categories": { 
     "type": "string", 
     "index": "not_analyzed" 
     }, 
     "seller": { 
     "type": "nested", 
     "properties": { 
      "id": { 
      "type": "integer", 
      "index": "not_analyzed" 
      }, 
      "username": { 
      "type": "string", 
      "analyzer": "custom_analyzer", 
      "boost": 1 
      }, 
      "firstName": { 
      "type": "string", 
      "analyzer": "custom_analyzer", 
      "boost": 3 
      }, 
      "lastName": { 
      "type": "string", 
      "analyzer": "custom_analyzer", 
      "boost": 2 
      } 
     } 
     }, 
     "marketPrice": { 
     "type": "float", 
     "index": "not_analyzed" 
     }, 
     "currentPrice": { 
     "type": "float", 
     "index": "not_analyzed" 
     }, 
     "discount": { 
     "type": "float", 
     "index": "not_analyzed" 
     }, 
     "commentsCount": { 
     "type": "integer", 
     "index": "not_analyzed" 
     }, 
     "likesCount": { 
     "type": "integer", 
     "index": "not_analyzed" 
     }, 
     "featured": { 
     "type": "boolean", 
     "index": "not_analyzed" 
     }, 
     "bumped": { 
     "type": "boolean", 
     "index": "not_analyzed" 
     }, 
     "created": { 
     "type": "date", 
     "index": "not_analyzed" 
     }, 
     "modified": { 
     "type": "date", 
     "index": "not_analyzed" 
     } 
    } 
    } 

И этот запрос:

GET /develop/_search?search_type=dfs_query_then_fetch 
{ 
    "query": { 
    "filtered" : { 
     "query": { 
      "bool": { 
      "must": [ 
       { "match": { "title": "post" }} 
      ] 
      } 
     }, 
     "filter": { 
      "bool": { 
      "must": [ 
       {"term": { 
       "featured": 0 
       }}, 
       { 
       "nested": { 
       "path": "seller", 
       "filter": { 
        "bool": { 
        "must": [ 
         { "term": { "seller.firstName": "Test 3" } } 
        ] 
        } 
       }, 
       "_cache" : true 
       }} 
      ] 
      } 
     } 
    } 
    }, 
    "sort": [ 
    { 
     "_score":{ 
     "order": "desc" 
     } 
    },{ 
     "created": { 
     "order": "desc" 
     } 
    } 
    ], 
    "track_scores": true 
} 

я жду 25 результатов, потому что у меня есть 25 после индексации. Но я получаю пустой набор. Если я удаляю вложенный фильтр, все работает нормально. Я хочу, чтобы иметь возможность фильтровать для вложенного объекта

EDIT:

В моих настройках у меня есть:

"analyzer": { 
     "custom_analyzer": { 
     "type": "custom", 
     "tokenizer": "nGram", 
     "filter": [ 
      "stopwords", 
      "asciifolding", 
      "lowercase", 
      "snowball", 
      "english_stemmer", 
      "english_possessive_stemmer", 
      "worddelimiter" 
     ] 
     }, 
     "custom_search_analyzer": { 
     "type": "custom", 
     "tokenizer": "standard", 
     "filter": [ 
      "stopwords", 
      "asciifolding", 
      "lowercase", 
      "snowball", 
      "english_stemmer", 
      "english_possessive_stemmer", 
      "worddelimiter" 
     ] 
     } 
    } 

Что им не хватает здесь.

Благодаря

+0

Вы можете оставить определение 'custom_analyzer'? Способ, которым он настроен, может иметь какое-то отношение к вашей проблеме. –

+0

hey @SloanAhrens я обновляю вопрос с помощью моих анализаторов – bitgandtter

+0

Я все еще не могу настроить индекс, подобный вашему, чтобы проверить его.Похоже, что у вас есть определенные пользовательские фильтры? Можете ли вы опубликовать их также? Некоторые примеры документов также могут оказаться полезными. Трудно сказать вам, в чем проблема, не имея возможности имитировать вашу систему. –

ответ

3

Короткая версия: попробовать это (после обновления конечной точки и имя индекса):

curl -XPOST "http://localhost:9200/my_index/_search?search_type=dfs_query_then_fetch" -d' 
{ 
    "query": { 
     "filtered": { 
     "query": { 
      "bool": { 
       "must": [ 
        { 
        "match": { 
         "title": "post" 
        } 
        } 
       ] 
      } 
     }, 
     "filter": { 
      "bool": { 
       "must": [ 
        { 
        "nested": { 
         "path": "seller", 
         "filter": { 
          "bool": { 
           "must": [ 
           { 
            "terms": { 
             "seller.firstName": [ 
              "test", 
              "3" 
             ], 
             "execution": "and" 
            } 
           } 
           ] 
          } 
         } 
        } 
        } 
       ] 
      } 
     } 
     } 
    } 
}' 

Он работал для меня, с упрощенной версии вашей установки. Через некоторое время я опубликую какое-нибудь изменение с более длинным объяснением.

EDIT: длинная версия:

Проблема с запросом является анализатор в сочетании с term фильтра в запросе. Ваш анализатор разбивает текст поля firstName на токены; поэтому "Test 3" становится токенами "test" и "3". Когда вы используете { "term": { "seller.firstName": "Test 3" } }, что вы говорите, найдите документ, в котором один из токенов для "seller.firstName" - "Test 3", и нет никаких документов, для которых это правда (на самом деле не может быть предоставлен способ анализатора установлен). Вы можете использовать "index": "not_analyzed" в этом поле, а затем ваш запрос будет работать, или вы можете использовать фильтр terms, как показано выше. Вот как я туда попал:

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

curl -XDELETE "http://localhost:9200/my_index" 

curl -XPUT "http://localhost:9200/my_index" -d' 
{ 
    "settings": { 
     "number_of_shards": 1, 
     "number_of_replicas": 0, 
     "analysis": { 
     "filter": { 
      "snowball": { "type": "snowball", "language": "English" }, 
      "english_stemmer": { "type": "stemmer", "language": "english" }, 
      "english_possessive_stemmer": { "type": "stemmer", "language": "possessive_english" }, 
      "stopwords": { "type": "stop", "stopwords": [ "_english_" ] }, 
      "worddelimiter": { "type": "word_delimiter" } 
     }, 
     "tokenizer": { 
      "nGram": { "type": "nGram", "min_gram": 3, "max_gram": 20 } 
     }, 
     "analyzer": { 
      "custom_analyzer": { 
       "type": "custom", 
       "tokenizer": "nGram", 
       "filter": [ 
        "stopwords", 
        "asciifolding", 
        "lowercase", 
        "snowball", 
        "english_stemmer", 
        "english_possessive_stemmer", 
        "worddelimiter" 
       ] 
      }, 
      "custom_search_analyzer": { 
       "type": "custom", 
       "tokenizer": "standard", 
       "filter": [ 
        "stopwords", 
        "asciifolding", 
        "lowercase", 
        "snowball", 
        "english_stemmer", 
        "english_possessive_stemmer", 
        "worddelimiter" 
       ] 
      } 
     } 
     } 
    }, 
    "mappings": { 
     "posts": { 
     "properties": { 
      "title": { 
       "type": "string", 
       "analyzer": "custom_analyzer", 
       "boost": 5 
      }, 
      "seller": { 
       "type": "nested", 
       "properties": { 
        "firstName": { 
        "type": "string", 
        "analyzer": "custom_analyzer", 
        "boost": 3 
        } 
       } 
      } 
     } 
     } 
    } 
}' 

Затем я добавил несколько тестов Документов

curl -XPUT "http://localhost:9200/my_index/posts/1" -d' 
{"title": "post", "seller": {"firstName":"Test 1"}}' 
curl -XPUT "http://localhost:9200/my_index/posts/2" -d' 
{"title": "post", "seller": {"firstName":"Test 2"}}' 
curl -XPUT "http://localhost:9200/my_index/posts/3" -d' 
{"title": "post", "seller": {"firstName":"Test 3"}}' 

Затем запустили упрощенную версию запроса с основной структурой по-прежнему нетронутой, но с terms фильтром вместо term фильтра:

curl -XPOST "http://localhost:9200/my_index/_search?search_type=dfs_query_then_fetch" -d' 
{ 
    "query": { 
     "filtered": { 
     "query": { 
      "bool": { 
       "must": [ 
        { 
        "match": { 
         "title": "post" 
        } 
        } 
       ] 
      } 
     }, 
     "filter": { 
      "bool": { 
       "must": [ 
        { 
        "nested": { 
         "path": "seller", 
         "filter": { 
          "bool": { 
           "must": [ 
           { 
            "terms": { 
             "seller.firstName": [ 
              "test", 
              "3" 
             ], 
             "execution": "and" 
            } 
           } 
           ] 
          } 
         } 
        } 
        } 
       ] 
      } 
     } 
     } 
    } 
}' 
... 
{ 
    "took": 5, 
    "timed_out": false, 
    "_shards": { 
     "total": 1, 
     "successful": 1, 
     "failed": 0 
    }, 
    "hits": { 
     "total": 1, 
     "max_score": 6.085842, 
     "hits": [ 
     { 
      "_index": "my_index", 
      "_type": "posts", 
      "_id": "3", 
      "_score": 6.085842, 
      "_source": { 
       "title": "post", 
       "seller": { 
        "firstName": "Test 3" 
       } 
      } 
     } 
     ] 
    } 
} 

который, кажется, возвращает то, что вы хотите.

Вот код, который я использовал:

http://sense.qbox.io/gist/041dd929106d27ea606f48ce1f86076c52faec91

+0

Отлично, что работает, но ES не должен делать это для меня? как я могу определить анализатор для использования в фильтре? потому что, если мне нужно сделать анализ текста поиска, я могу быть довольно жестким. – bitgandtter

+0

Прочтите редактирование, которое я только что сделал, и посмотрим, отвечает ли он на ваш вопрос. Если нет, я посмотрю, смогу ли я его обновить. Я ожидаю, что вы захотите изменить свой анализатор и/или использовать multi_field. –

+0

Спасибо Sloan, после того, как вы опубликовали ответ, я понял, что custom_analyzer его разделяет поле, но то, что я хочу, чтобы он использовал custom_search_analyzer в запросе, поэтому в момент использования фильтры ES разбивают текст на него, поэтому я не нужно разделить его на себя и построить запрос таким образом. У меня есть другой запрос с «multi_match»: { «query»: «post», «fields»: ["title", "description"], "analyzer": "custom_search_analyzer" } в нем то, что я хочу что-то подобное – bitgandtter

Смежные вопросы