Elasti c Search 2.0 поисковый запрос в основном и вложенном объектах - PullRequest
1 голос
/ 04 мая 2020

Это моя модель:

public class Student
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    [Nested]
    public List<Subject> Subjects { get; set; }
}

public class Subject
{
    public int Id { get; set; }
    public string SubjectName { get; set; }        
}

Отображение:

mappings: {
  student: {
    properties: {
      firstName: {
        type: "string"
      },
      id: {
        type: "integer"
      },
      lastName: {
        type: "string"
      },
      subjects: {
        type: "nested",
        properties: {
          id: {
            type: "integer"
          },
          subjectName: {
            type: "string"
          }
       } 
    }
 }
}
}

Для поиска во вложенном объекте (Subject) я использую следующий код, и он возвращает значения правильно.

var searchResponse = client.Search<Student>(s => s    
.Query(q => q
    .Nested(n => n
        .Path(p => p.VolunteerTasks)
        .Query(nq => nq.Match(m => m
            .Query(searchText).Field("subjects.subjectName"))))));
 return searchResponse.Documents;

Но я хочу найти с тем же searchText для student.firstName, student.lastName и subjects.subjectName. Как я могу это сделать?

Ответы [ 3 ]

1 голос
/ 04 мая 2020

Вам необходимо добавить предложение must с запросом на совпадение имени и фамилии и вложенным запросом на имя субъекта. Вы не можете объединить вложенные и не вложенные запросы в один или несколько совпадений

var searchResponse = _elasticClient.Search<AssociateProfile>(s => s
                     .Query(q => q
                                 .Bool(b=>b
                                             .Should(
                                                        sh => sh.Match(m => m.Query(searchText).Field("student.firstName")),
                                                        sh => sh.Match(m => m.Query(searchText).Field("student.lastName")),
                                                         sh => sh.Nested(n => n
                                                                               .Path(p => p.VolunteerTasks)                                                                                           .Query(nq => nq.Match(m => m                                                                                           .Query(searchText).Field("subjects.subjectName")))
                                                                                    )

                                                                   )
                                                    )
                                              ));
1 голос
/ 09 мая 2020

На основе комментария от OP, Добавление ответа, который обеспечивает частичное совпадение. например, если документ содержит Science and technology и поиск techno также должен прийти. Обратите внимание на использование пользовательского анализатора edge-n-грамм для достижения этого требования.

Определение индекса

{
  "settings": {
    "analysis": {
      "filter": {
        "autocomplete_filter": {
          "type": "edge_ngram",
          "min_gram": 1,
          "max_gram": 10
        }
      },
      "analyzer": {
        "autocomplete": { 
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "autocomplete_filter"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "autocomplete", 
        "search_analyzer": "standard" 
      }
    }
  }
}

Пример индекса c

{
    "title" : "Science and technology"
}

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

{
    "query" :{
        "match" :{
            "title" :"techno"
        }
    }
}

Результат поиска

 "hits": [
            {
                "_index": "edge",
                "_type": "_doc",
                "_id": "1",
                "_score": 0.44104567,
                "_source": {
                    "title": "Science and technology"
                }
            }
        ]
1 голос
/ 04 мая 2020

Предоставление ответа в форме REST API, который вы можете преобразовать в формат c#, так как я не знаком с его синтаксисом, и это было бы полезно для людей, которые не ищут языковые c ответы.

Протестировано это с вашими примерами данных, ниже приведено рабочее решение .

Индекс Def

{
    "student": {
        "properties": {
            "firstName": {
                "type": "string"
            },
            "id": {
                "type": "integer"
            },
            "lastName": {
                "type": "string"
            },
            "subjects": {
                "type": "nested",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "subjectName": {
                        "type": "string"
                    }
                }
            }
        }
    }
}

** Индексный образец делает c, который не имеет opster либо subject и firstname **

{
    "firstName": "Isuru",
    "lastName": "foo",
    "id": 1,
    "subjects": [
        {
            "id": 100,
            "subjectName": "math"
        },
        {
            "id": 101,
            "subjectName": "opster"
        }
    ]
}

Индексирует другой do c, который не имеет opster в любой теме

{
    "firstName": "opster",
    "lastName": "tel aviv",
    "id": 1,
    "subjects": [
        {
            "id": 100,
            "subjectName": "math"
        },
        {
            "id": 101,
            "subjectName": "science"
        }
    ]
}

Поисковый запрос, пожалуйста, измените must на should в соответствии с вашими требованиями

{
    "query": {
        "bool": {
            "should": [    --> note
                {
                    "match": {
                        "firstName": "opster"
                    }
                },
                {
                    "nested": {
                        "path": "subjects",
                        "query": {
                            "bool": {
                                "must": [   -->note
                                    {
                                        "match": {
                                            "subjects.subjectName": "opster"
                                        }
                                    }
                                ]
                            }
                        }
                    }
                }
            ]
        }
    }
}

Результат поиска

"hits": [
            {
                "_index": "nested",
                "_type": "student",
                "_id": "1",
                "_score": 0.39103588,
                "_source": {
                    "firstName": "opster",
                    "lastName": "tel aviv",
                    "id": 1,
                    "subjects": [
                        {
                            "id": 100,
                            "subjectName": "math"
                        },
                        {
                            "id": 101,
                            "subjectName": "science"
                        }
                    ]
                }
            },
            {
                "_index": "nested",
                "_type": "student",
                "_id": "2",
                "_score": 0.39103588,
                "_source": {
                    "firstName": "Isuru",
                    "lastName": "foo",
                    "id": 1,
                    "subjects": [
                        {
                            "id": 100,
                            "subjectName": "math"
                        },
                        {
                            "id": 101,
                            "subjectName": "opster"
                        }
                    ]
                }
            }
        ]
...