2015-11-25 1 views
1

Я работаю над медицинским проектом, где у меня есть несколько вопросов вместе с темами, прилагаемыми к ним. Проблема в том, что следующий код работает нормально, но он не учитывает фильтр «must_not», тогда как он отлично работает с предложением «must». Помогите мне с этим.Elasticsearch must_not не работает с предложением фильтра

GET stopdata/_search 
{ 
    "query": { 
    "function_score": { 
     "query": { 
     "filtered": { 
      "query": { 
      "match": { 
       "question": "Hello Dr. Iam suffering from fever with cough nd cold since 3 days" 
      } 
      } 
     } 
     }, 
     "filter": { 
     "bool": { 
      "must": [ 
      { 
       "terms": { 
       "topics": [ 
        "fever", 
        "cough" 
       ] 
       } 
      } 
      ], 
      "must_not": [ 
      { 
       "terms": { 
       "topics": [ 
        "children", 
        "child", 
        "childrens health" 
       ] 
       } 
      } 
      ] 
     } 
     }, 
     "random_score": {} 
    } 
    }, 
    "highlight": { 
    "fields": { 
     "keyword": {} 
    } 
    } 
} 

Кроме того, мне нужно преобразовать код в Java, который я пытаюсь, но придерживался следующего кода.

Set<String> mustNot = new HashSet<String>(); 
mustNot.add("child"); 
mustNot.add("children"); 
mustNot.add("childrens health"); 

Set<String> must = new HashSet<String>(); 
must.add("fever"); 
must.add("cough"); 

FunctionScoreQueryBuilder fsqb = new FunctionScoreQueryBuilder(QueryBuilders.matchQuery("question", "Hello Dr. Iam suffering from fever with cough nd cold since 3 days")); 
fsqb.add(ScoreFunctionBuilders.randomFunction((new Date()).getTime())); 

BoolQueryBuilder bqb = boolQuery() 
     .mustNot(termsQuery("topics", mustNot)); 

SearchResponse response1 = client.prepareSearch("stopdata") 
     .setQuery(fsqb) 
     .execute() 
     .actionGet(); 

System.out.println(response1.getHits().getTotalHits()); 

Отображение проиндексирует «stopdata» как следовать

{ 
    "stopdata": { 
     "mappings": { 
     "questions": { 
      "properties": { 
       "answers": { 
        "type": "string" 
       }, 
       "id": { 
        "type": "long" 
       }, 
       "question": { 
        "type": "string", 
        "analyzer": "my_english" 
       }, 
       "relevantQuestions": { 
        "type": "long" 
       }, 
       "topics": { 
        "type": "string" 
       } 
      } 
     } 
     } 
    } 
} 

Добавление выборочных данных для указанного выше показателя

"question": "My son of age 8 months is suffering from cough and cold and fever. What treatment I have to follow?" 
"topics": [ 
    "Cough", 
    "Fever", 
    "Hydration", 
    "Nutrition", 
    "Tens", 
    "Childrens health" 
] 

"question": "Hi.My daughter, 4 years old , has on and of fever with severe coughing and colds for 3 days now.She vomited as well last night.Do you think it's viral?" 
"topics": [ 
    "Vomiting", 
    "Flu", 
    "Cough", 
    "Fever", 
    "Pneumonia", 
    "Meningitis", 
    "Tamiflu", 
    "Incision", 
    "Childrens health", 
    "Oseltamivir" 
] 

"question": "If you have a fever of 101 with chills and sweats for 2 day with a slight cough, should you go to the drs or let is wear off?" 
"topics": [ 
    "Cough", 
    "Fever" 
] 

ответ

1

То, что я вижу, что вся filter части является неуместным, он должен войти в запрос filtered, потому что нет элемента filter в корне элемента function_score (см. official docs). Таким образом, ваш запрос должен выглядеть в первую очередь + вы должны использовать POST вместо GET, так как вы отправляете полезный груз:

POST stopdata/_search 
{ 
    "query": { 
    "function_score": { 
     "query": { 
     "filtered": { 
      "query": { 
      "match": { 
       "question": "Hello Dr. Iam suffering from fever with cough nd cold since 3 days" 
      } 
      }, 
      "filter": { 
      "bool": { 
       "must": [ 
       { 
        "terms": { 
        "topics": [ 
         "fever", 
         "cough" 
        ] 
        } 
       } 
       ], 
       "must_not": [ 
       { 
        "terms": { 
        "topics": [ 
         "children", 
         "child", 
         "childrens health" 
        ] 
        } 
       } 
       ] 
      } 
      } 
     } 
     }, 
     "random_score": {} 
    } 
    }, 
    "highlight": { 
    "fields": { 
     "keyword": {} 
    } 
    } 
} 

Теперь, чтобы написать все это в Java, это выглядит следующим образом:

Set<String> mustNot = new HashSet<String>(); 
mustNot.add("child"); 
mustNot.add("children"); 
mustNot.add("childrens health"); 

Set<String> must = new HashSet<String>(); 
must.add("fever"); 
must.add("cough"); 

MatchQueryBuilder query = QueryBuilders.matchQuery("question", "Hello Dr. Iam suffering from fever with cough nd cold since 3 days"); 

BoolFilterBuilder filter = FilterBuilders.boolFilter() 
    .must(FilterBuilders.termsFilter("topics", must)) 
    .mustNot(FilterBuilders.termsFilter("topics", mustNot)); 

FilteredQueryBuilder fqb = QueryBuilders.filteredQuery(query, filter); 

FunctionScoreQueryBuilder fsqb = QueryBuilders.functionScoreQuery(fqb); 
fsqb.add(ScoreFunctionBuilders.randomFunction((new Date()).getTime())); 

SearchResponse response1 = client.prepareSearch("stopdata") 
     .setQuery(fsqb) 
     .execute() 
     .actionGet(); 

System.out.println(response1.getHits().getTotalHits()); 

UPDATE

причина, почему must_not не соответствует childrens health потому, что topics поле анализируется и, таким образом, получает Childrens health лексемы и анализируется как два токена childrens и health, таким образом, попытка terms матча на childrens health ничего не даст. Может быть, разделение на два срока помогло бы:

   "must_not": [ 
       { 
        "terms": { 
        "topics": [ 
         "children", 
         "child", 
         "childrens", 
         "health" 
        ] 
        } 
       } 
       ] 
+0

Я до сих пор получаю результаты по темам «здоровье детей», нет изменений в результате, как вы предложили. – JDpawar

+0

Я просто фиксировал 1) семантическую проблему в вашем запросе и 2) помогал вам создавать эквивалент Java. В конце концов, то, что соответствует, зависит от ваших данных и того, как выглядит ваше сопоставление для поля 'themes', не стесняйтесь делиться дополнительной информацией об этом. – Val

+0

Благодарим вас за помощь Val. Я добавил отображение и образцы данных. Кроме того, я получаю ошибку в 'FilteredQueryBuilder fqb = QueryBuilders.filteredQuery (запрос, фильтр);' ''Метод filterQuery (QueryBuilder, FilterBuilder) в типе QueryBuilders не применим для аргументов (MatchQueryBuilder, BoolQueryBuilder)'' – JDpawar