Поиск с более чем одним параметром по нескольким полям в elasti c search - PullRequest
1 голос
/ 14 апреля 2020

Я хочу вернуть этот курс только в том случае, если 'Grade' = 'G6' и Type = 'Open' совпадают в теге SAME аудитория, они должны существовать в теге SAME для возврата этого курса. В настоящее время этот курс возвращается, если он находит G6 и ОТКРЫТАЯ РАЗНАЯ аудитория, а это не то, чего я хочу Это неверно, и я получаю неверные данные обратно, мне нужно запросить данные для каждой аудитории и вернуть данные только в том случае, если они верны для той же аудитории

вот мой json:

{
"took": 1,
"timed_out": false,
"_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
},
"hits": {
    "total": 71,
    "max_score": 3.3118114,
    "hits": [
        {
            "_index": "courses",
            "_type": "course",
            "_id": "LBTBWdzyRw-jgiiYssjv8A",
            "_score": 3.3118114,
            "_source": {
                "id": "LBTBWdzyRw-jgiiYssjv8A",
                "title": "1503 regression testing",
                "shortDescription": "asdf",
                "description": "asdf",
                "learningOutcomes": "",
                "modules": [],
                "learningProvider": {
                    "id": "ig2-zIY_QkSpMC4O0Lm0hw",
                    "name": null,
                    "termsAndConditions": [],
                    "cancellationPolicies": []
                },
                "audiences": [
                    {
                        "id": "VfDpsS_5SXi8iZubzTkUBQ",
                        "name": "comm",
                        "areasOfWork": [
                            "Communications"
                        ],
                        "departments": [],
                        "grades": [
                            "G6"
                        ],
                        "interests": [],
                        "requiredBy": null,
                        "frequency": null,
                        "type": "OPEN",
                        "eventId": null
                    },
                    {
                        "id": "eZPPPqTqRdiDAE3xCPlJMQ",
                        "name": "analysis",
                        "areasOfWork": [
                            "Analysis"
                        ],
                        "departments": [],
                        "grades": [
                            "G6"
                        ],
                        "interests": [],
                        "requiredBy": null,
                        "frequency": null,
                        "type": "REQUIRED",
                        "eventId": null
                    }
                ],
                "preparation": "",
                "owner": {
                    "scope": "LOCAL",
                    "organisationalUnit": "co",
                    "profession": 63,
                    "supplier": ""
                },
                "visibility": "PUBLIC",
                "status": "Published",
                "topicId": ""
            }
        }
    ]
}

}

Мой код ES:

 BoolQueryBuilder boolQuery = boolQuery();

    boolQuery.should(QueryBuilders.matchQuery("audiences.departments.keyword", department));
    boolQuery.should(QueryBuilders.matchQuery("audiences.areasOfWork.keyword", areaOfWork));
    boolQuery.should(QueryBuilders.matchQuery("audiences.interests.keyword", interest));

    BoolQueryBuilder filterQuery = boolQuery();
    filterQuery.must(QueryBuilders.matchQuery("audiences.grades.keyword", "G6"));
    filterQuery.must(QueryBuilders.matchQuery("audiences.type", "OPEN"));

Вот отображение индекса:

{
  "media": {
    "aliases": {}
  },
  "courses": {
    "aliases": {}
  },
  "feedback": {
    "aliases": {}
  },
  "learning-providers": {
    "aliases": {}
  },
  "resources": {
    "aliases": {}
  },
  "courses-0.4.0": {
    "aliases": {}
  },
  ".security-6": {
    "aliases": {
      ".security": {}
    }
  },
  "payments": {
    "aliases": {}
  }
}

1 Ответ

1 голос
/ 17 апреля 2020

Поскольку вы хотите указать query to apply in each audience and only return data if it is true in the same audience, вам необходимо указать вложенный тип данных для поля audiences, в противном случае ElasticSearch сохраняет его в виде объектов и не имеет концепции вложенных объектов, из-за чего Elasticsearch сглаживает иерархии объектов в простой список Имена полей и значения. Вы можете сослаться на это для более подробной информации https://www.elastic.co/guide/en/elasticsearch/reference/current/nested.html

Принимая ваш пример, предположим, что это был ваш документ:

    "audiences": [
            {
                "id": "1",
                "field": "comm"
            },
           {
                "id": "2",
                "field": "arts"
           }
   ]

Elasticsearch сглаживается в виде из:

{
   "audiences.id":[1,2],
   "audiences.field":[comm,arts]
}

Теперь здесь, если вы выполняете поисковый запрос, говорится, что аудитория должна иметь id: 1 и field: art, тогда и вышеупомянутый документ будет совпадать.

Итак, в Чтобы избежать этого, такой тип объектов должен быть определен как nested объект. ElasticSearch будет хранить каждый объект отдельно, а не сглаживать его, в результате каждый объект будет найден отдельно.

Отображение вашего вышеупомянутого документа должно быть:

Отображение

{
    "mappings": {
        "properties": {
            "shortDescription": {
                "type": "text"
            },
            "audiences": {
                "type": "nested"
            },
            "description": {
                "type": "text"
            },
            "modules": {
                "type": "text"
            },
            "preparation": {
                "type": "text"
            },
            "owner": {
                "properties": {
                    "scope": {
                        "type": "text"
                    },
                    "organisationalUnit": {
                        "type": "text"
                    },
                    "profession": {
                        "type": "text"
                    },
                    "supplier": {
                        "type": "text"
                    }
                }
            },
            "learningProvider": {
                "properties": {
                    "id": {
                        "type": "text"
                    },
                    "name": {
                        "type": "text"
                    },
                    "termsAndConditions": {
                        "type": "text"
                    },
                    "cancellationPolicies": {
                        "type": "text"
                    }
                }
            },
            "visibility": {
                "type": "text"
            },
            "status": {
                "type": "text"
            },
            "topicId": {
                "type": "text"
            }
        }
    }
}

Теперь, если мы проиндексируем этот документ:

Документ

{
    "shortDescription": "asdf",
    "description": "asdf",
    "learningOutcomes": "",
    "modules": [],
    "learningProvider": {
        "id": "ig2-zIY_QkSpMC4O0Lm0hw",
        "name": null,
        "termsAndConditions": [],
        "cancellationPolicies": []
    },
    "audiences": [
        {
            "id": "VfDpsS_5SXi8iZubzTkUBQ",
            "name": "comm",
            "areasOfWork": [
                "Communications"
            ],
            "departments": [],
            "grades": [
                "G6"
            ],
            "interests": [],
            "requiredBy": null,
            "frequency": null,
            "type": "OPEN",
            "eventId": null
        },
        {
            "id": "eZPPPqTqRdiDAE3xCPlJMQ",
            "name": "analysis",
            "areasOfWork": [
                "Analysis"
            ],
            "departments": [],
            "grades": [
                "G7"
            ],
            "interests": [],
            "requiredBy": null,
            "frequency": null,
            "type": "REQUIRED",
            "eventId": null
        }
    ],
    "preparation": "",
    "owner": {
        "scope": "LOCAL",
        "organisationalUnit": "co",
        "profession": 63,
        "supplier": ""
    },
    "visibility": "PUBLIC",
    "status": "Published",
    "topicId": ""
}

Если вы выполняете поисковый запрос так:

Поисковый запрос 1

:

{
"query": {
    "nested": {
        "path": "audiences",

        "query": {
            "bool": {
                "must": [
                    {
                        "match": {
                            "audiences.type.keyword": "OPEN"
                        }

                    },
                     {
                        "match": {
                            "audiences.grades.keyword": "G6"
                        }

                    }
                ]
            }
        }

    }
}

}

Результат

"hits": [
        {
            "_index": "product",
            "_type": "_doc",
            "_id": "1",
            "_score": 0.9343092,
            "_source": {
                "shortDescription": "asdf",
                "description": "asdf",
                "learningOutcomes": "",
                "modules": [],
                "learningProvider": {
                    "id": "ig2-zIY_QkSpMC4O0Lm0hw",
                    "name": null,
                    "termsAndConditions": [],
                    "cancellationPolicies": []
                },
                "audiences": [
                    {
                        "id": "VfDpsS_5SXi8iZubzTkUBQ",
                        "name": "comm",
                        "areasOfWork": [
                            "Communications"
                        ],
                        "departments": [],
                        "grades": [
                            "G6"
                        ],
                        "interests": [],
                        "requiredBy": null,
                        "frequency": null,
                        "type": "OPEN",
                        "eventId": null
                    },
                    {
                        "id": "eZPPPqTqRdiDAE3xCPlJMQ",
                        "name": "analysis",
                        "areasOfWork": [
                            "Analysis"
                        ],
                        "departments": [],
                        "grades": [
                            "G7"
                        ],
                        "interests": [],
                        "requiredBy": null,
                        "frequency": null,
                        "type": "REQUIRED",
                        "eventId": null
                    }
                ],
                "preparation": "",
                "owner": {
                    "scope": "LOCAL",
                    "organisationalUnit": "co",
                    "profession": 63,
                    "supplier": ""
                },
                "visibility": "PUBLIC",
                "status": "Published",
                "topicId": ""
            }
        }
    ]

Но теперь, если ваш поисковый запрос:

Поисковый запрос 2:

{
    "query": {
        "nested": {
            "path": "audiences",

            "query": {
                "bool": {
                    "must": [
                        {
                            "match": {
                                "audiences.type.keyword": "OPEN"
                            }

                        },
                         {
                            "match": {
                                "audiences.grades.keyword": "G7"
                            }

                        }
                    ]
                }
            }

        }
    }
}

Результат:

"hits": {
        "total": {
            "value": 0,
            "relation": "eq"
        },
        "max_score": null,
        "hits": []
}

Итак, короче говоря, вам нужно изменить тип данных поля audiences в вашем отображении и запросе отдыха, чтобы он мог искать вложенный тип данных.

Таким образом, вместо этого фрагмента кода:

BoolQueryBuilder filterQuery = boolQuery();
filterQuery.must(QueryBuilders.matchQuery("audiences.grades.keyword", "G6"));
filterQuery.must(QueryBuilders.matchQuery("audiences.type", "OPEN"));

вы должны использовать этот вложенный запрос:

BoolQueryBuilder filterQuery = new BoolQueryBuilder();
filterQuery.must(QueryBuilders.matchQuery("audiences.grades.keyword", "G6"));
filterQuery.must(QueryBuilders.matchQuery("audiences.type", "OPEN"));
NestedQueryBuilder nested = new NestedQueryBuilder("audiences", filterQuery, ScoreMode.None);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...