简体   繁体   English

NEST Api Search在NEST中返回null,但在Kibana中有效

[英]NEST Api SearchAfter return null in NEST but works in Kibana

We are using elastic search just for document search in our application so we don't have any one expert in it. 我们仅在应用程序中将弹性搜索用于文档搜索,因此我们没有任何专家。 I was able to use TermQuery , SimpleQueryStringQuery and MatchPhraseQuery successfully. 我能够成功使用TermQuerySimpleQueryStringQueryMatchPhraseQuery But I found out in documentation that using From & Size for pagination is not good for production and Search After is recommended. 但是我在文档中发现使用FromSize进行分页并不适合生产,建议使用Search After。

But my implementation return null . 但是我的实现返回null It is confusing for me what should be in <Project> parameter as shown in Nest API Object Initializer Syntax in docs here . 令我困惑的是<Project>参数中应该包含什么,如docs中的Nest API Object Initializer语法所示。

My code looks like this: 我的代码如下所示:

var request = new SearchRequest<ElasticSearchJsonObject._Source>
 {
    //Sort = new List<ISort>
    //{
    //    new SortField { Field = Field<ElasticSearchJsonObject>(p=>)}
    //},
    SearchAfter = new List<object> {

    },                    
    Size = 20,
    Query = query
  };                               

Reality is I don't understand this. 现实是我不明白这一点。 Over here ElasticSearchJsonObject._Source is the class to map returned results. 在这里, ElasticSearchJsonObject._Source是映射返回结果的类。

My documents are simple text documents and I only want documents sorted according to score so document Id is not relevant. 我的文档是简单的文本文档,我只希望文档按照分数排序,因此文档ID不相关。

There was already a question like this on SO but I can't find it somehow. 在SO上已经存在这样的问题,但我无法以某种方式找到它。


Update 更新

After looking at answer I updated my code and though query obtained does work. 查看答案后,我更新了代码,尽管获得的查询确实有效。 It return result in kibana but not in NEST. 它以kibana返回结果,但不以NEST返回结果。

This is the new updated code: 这是新的更新代码:

var request = new SearchRequest<ElasticSearchJsonObject.Rootobject>
            {
                Sort = new List<ISort>
                {
                    new SortField { Field = "_id", Order = SortOrder.Descending}
                },
                SearchAfter = new List<object> {
                   "0fc3ccb625f5d95b973ce1462b9f7"
                },                    
                Size = 1,
                Query = query
            };

Over here I am using size=1 just for test as well as hard code _id value in SearchAfter . 在这里,我将size=1用于测试以及SearchAfter硬代码_id值。

The query generated by NEST is: NEST生成的查询是:

{
  "size": 1,
  "sort": [
    {
      "_id": {
        "order": "desc"
      }
    }
  ],
  "search_after": [
    "0fc3ccb625f5d95b973ce1462b9f7"
  ],
  "query": {
    "match": {
      "content": {
        "query": "lahore",
        "fuzziness": "AUTO",
        "prefix_length": 3,
        "max_expansions": 10
      }
    }
  }
}

The response from the ES does say successful but no results are returned. ES的响应确实表示成功,但未返回任何结果。

  • Results do return in Kibana 结果确实在Kibana中返回
  • Query status is successful 查询状态成功
  • But... 但...
  • Total returned is 0 in NEST 在NEST中返回的总数为0
  • Sort value is null in kibana I used TrackScores = true to solve this issue 在kibana中,sort值为null 我使用TrackScores = true解决了此问题

Here is the debug information: 这是调试信息:

Valid NEST response built from a successful low level call on POST: /extract/_source/_search?typed_keys=true
# Audit trail of this API call:
 - [1] HealthyResponse: Node: http://localhost:9200/ Took: 00:00:00.1002662
# Request:
{"size":1,"sort":[{"_id":{"order":"desc"}}],"search_after":["0fc3ccb625f5d95b973ce1462b9f7"],"query":{"match":{"content":{"query":"lahore","fuzziness":"AUTO","prefix_length":3,"max_expansions":10}}}}
# Response:
{"took":3,"timed_out":false,"_shards":{"total":5,"successful":5,"skipped":0,"failed":0},"hits":{"total":0,"max_score":null,"hits":[]}}

So please tell me where I am wrong and what can be the problem and how to solve it. 因此,请告诉我哪里错了,可能是什么问题以及如何解决。


Update 2: 更新2:

Code in Controller: 控制器中的代码:

Connection String: 连接字符串:

var node = new Uri("http://localhost:9200");
var settings = new ConnectionSettings(node);
settings.DisableDirectStreaming();
settings.DefaultIndex("extract");
var client = new ElasticClient(settings);

Query: 查询:

var query = (dynamic)null;
query = new MatchQuery
 {
    Field = "content",
    Query = content,
    Fuzziness = Fuzziness.Auto,
    PrefixLength = 3,
    MaxExpansions = 10
   };

Query Builder 查询生成器

var request = new SearchRequest<ElasticSearchJsonObject.Rootobject>
            {
                Sort = new List<ISort>
                {
                    new SortField { Field = "_id", Order = SortOrder.Descending}
                },
                SearchAfter = new List<object> {
                   documentid //sent as parameter
                },                    
                Size = 1, //for testing 1 other wise 10
                TrackScores = true,
                Query = query
            };

JSON Query I use this code to get query I posted above. JSON查询我使用此代码获取上面发布的查询。 This query is then passed to kibana with GET <my index name>/_Search and there it works 然后,此查询使用GET <my index name>/_Search传递给kibana,在这里有效

var stream = new System.IO.MemoryStream();
client.SourceSerializer.Serialize(request, stream);
var jsonQuery = System.Text.Encoding.UTF8.GetString(stream.ToArray());

ES Response ES回应

string responseJson = "";
                ElasticSearchJsonObject.Rootobject response = new ElasticSearchJsonObject.Rootobject();
                var res = client.Search<object>(request);
                if (res.ApiCall.ResponseBodyInBytes != null)
                {
                    responseJson = System.Text.Encoding.UTF8.GetString(res.ApiCall.ResponseBodyInBytes);
                    try
                    {
                        response = JsonConvert.DeserializeObject<ElasticSearchJsonObject.Rootobject>(responseJson);
                    }
                    catch (Exception)
                    {
                        var model1 = new LoginSignUpViewModel();
                        return PartialView("_NoResultPage", model1);
                    }
                }

This is where things go wrong. 这是出问题的地方。 Above debug information was captured from response 上面的调试信息是从response中捕获的

ElasticSearchJsonObject ElasticSearchJsonObject

Some how I think problem might be here somewhere? 我认为问题可能出在这里吗? The class is generated by taking response from NEST in Search request. 该类是通过在Search请求中获取NEST的响应而生成的。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace ESAPI
{
    public class ElasticSearchJsonObject
    {
        public class Rootobject
        {
            public int took { get; set; }
            public bool timed_out { get; set; }
            public _Shards _shards { get; set; }
            public Hits hits { get; set; }
        }

        public class _Shards
        {
            public int total { get; set; }
            public int successful { get; set; }
            public int skipped { get; set; }
            public int failed { get; set; }
        }

        public class Hits
        {
            public int total { get; set; }
            public float max_score { get; set; }
            public Hit[] hits { get; set; }
        }

        public class Hit
        {
            public string _index { get; set; }
            public string _type { get; set; }
            public string _id { get; set; }
            public float _score { get; set; }
            public _Source _source { get; set; }
        }

        public class _Source
        {
            public string content { get; set; }
            public Meta meta { get; set; }
            public File file { get; set; }
            public Path path { get; set; }
        }

        public class Meta
        {
            public string title { get; set; }
            public Raw raw { get; set; }
        }

        public class Raw
        {
            public string XParsedBy { get; set; }
            public string Originator { get; set; }
            public string dctitle { get; set; }
            public string ContentEncoding { get; set; }
            public string ContentTypeHint { get; set; }
            public string resourceName { get; set; }
            public string ProgId { get; set; }
            public string title { get; set; }
            public string ContentType { get; set; }
            public string Generator { get; set; }
        }

        public class File
        {
            public string extension { get; set; }
            public string content_type { get; set; }
            public DateTime last_modified { get; set; }
            public DateTime indexing_date { get; set; }
            public int filesize { get; set; }
            public string filename { get; set; }
            public string url { get; set; }
        }

        public class Path
        {
            public string root { get; set; }
            public string _virtual { get; set; }
            public string real { get; set; }
        }
    }
}

I am sure this can be used to get response. 我相信这可以用来获得回应。

Please note that in case of simple search this code works: 请注意,在简单搜索的情况下,此代码有效:

so for this query below my code is working: 因此,对于下面的查询,我的代码正在运行:

var request = new SearchRequest
                {
                    From = 0,
                    Size = 20,
                    Query = query
                };

Using from/size is not recommended for deep pagination because of the amount of documents that need to be fetched from all shards for a deep page , only to be discarded when finally returning an overall ordered result set. 不建议使用from / size进行深度分页,因为需要从所有分片中获取深页的文档数量,只有在最终返回整体有序结果集时才将其丢弃。 This operation is inherent to the distributed nature of Elasticsearch, and is common to many distributed systems in relation to deep pagination. 此操作是Elasticsearch的分布式特性所固有的,并且与深度分页有关,这是许多分布式系统所共有的。

With search_after , you can paginate forward through documents in a stateless fashion and it requires 随着search_after ,你可以在一个无状态的方式向前分页文件,通过它需要

  • the documents returned from the first search response are sorted (documents are sorted by _score by default) 从第一个搜索响应返回的文档进行排序(默认情况下,文档由_score排序)
  • passing the values for the sort fields of the last document in the hits from one search request as the values for "search_after": [] for the next request. 将来自一个搜索请求的匹配中的最后一个文档的排序字段的值作为"search_after": []的值传递给下一个请求。

In the Search After Usage documentation, a search request is made with sort on NumberOfCommits descending, then by Name descending. 在使用后搜索文档中,搜索请求按NumberOfCommits降序排序,然后按Name降序排序。 The values to use for each of these sort fields are passed in SearchAfter(...) and are the values of Project.First.NumberOfCommits and Project.First.Name properties, respectively. 用于每个这些排序字段的值在SearchAfter(...)中传递,分别是Project.First.NumberOfCommitsProject.First.Name属性的值。 This tells Elasticsearch to return documents that have values for the sort fields that correspond to the sort constraints for each field, and relate to the values supplied in the request. 这告诉Elasticsearch返回具有与每个字段的排序约束相对应并与请求中提供的值相关的排序字段值的文档。 For example, sort descending on NumberOfCommits with a supplied value of 775 means that Elasticsearch should only consider documents with a value less than 775 (and to do this for all sort fields and supplied values). 例如,按提供的值为775降序到NumberOfCommits ,表示Elasticsearch只应考虑值小于775的文档(并且对所有排序字段和提供的值都这样做)。

If you ever need to dig further into any NEST documentation, click the "EDIT" link on the page: 如果您需要进一步研究任何NEST文档,请单击页面上的"EDIT"链接:

Elasticsearch上的Elasticsearch文档

which will take you to the github repository of the documentation, with the original asciidoc markdown for the page: 它将带您到文档的github存储库,以及页面的原始asciidoc markdown:

Asciidoc文档来源

Within that page will be a link back to the original NEST source code from which the asciidoc was generated. 在该页面中,将有一个链接,指向原始NEST源代码的链接,从该源代码生成了asciidoc。 In this case, the original file is SearchAfterUsageTests.cs in the 6.x branch 在这种情况下,原始文件是6.x分支中的SearchAfterUsageTests.cs。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM