NEST Api SearchAfter 在 NEST 中返回 null 但在 Kibana 中有效
Posted
技术标签:
【中文标题】NEST Api SearchAfter 在 NEST 中返回 null 但在 Kibana 中有效【英文标题】:NEST Api SearchAfter return null in NEST but works in Kibana 【发布时间】:2018-03-26 10:52:37 【问题描述】:我们在我们的应用程序中仅使用弹性搜索来进行文档搜索,因此我们没有任何一位专家。我能够成功使用TermQuery
、SimpleQueryStringQuery
和MatchPhraseQuery
。但我在文档中发现使用From
和Size
进行分页不利于生产,建议使用搜索后。
但我的实现返回null
。正如 Nest API Object Initializer
语法 in docs here 中所示,<Project>
参数中应该包含什么让我感到困惑。
我的代码如下所示:
var request = new SearchRequest<ElasticSearchJsonObject._Source>
//Sort = new List<ISort>
//
// new SortField Field = Field<ElasticSearchJsonObject>(p=>)
//,
SearchAfter = new List<object>
,
Size = 20,
Query = query
;
现实是我不明白这一点。这里ElasticSearchJsonObject._Source
是映射返回结果的类。
我的文档是简单的文本文档,我只想根据分数对文档进行排序,因此文档 ID 不相关。
在 SO 上已经有这样的问题,但我找不到。
更新
查看答案后,我更新了我的代码,尽管获得的查询确实有效。它在 kibana 中返回结果,但不在 NEST 中。
这是新的更新代码:
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
;
在这里,我使用size=1
仅用于测试以及SearchAfter
中的硬代码_id
值。
NEST 生成的查询是:
"size": 1,
"sort": [
"_id":
"order": "desc"
],
"search_after": [
"0fc3ccb625f5d95b973ce1462b9f7"
],
"query":
"match":
"content":
"query": "lahore",
"fuzziness": "AUTO",
"prefix_length": 3,
"max_expansions": 10
来自 ES 的响应确实说成功,但没有返回任何结果。
结果在 Kibana 中返回 查询状态成功 但是…… NEST 中返回的总数为 0TrackScores = true
解决了这个问题
这里是调试信息:
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":[]
所以请告诉我我哪里错了,可能是什么问题以及如何解决它。
更新 2:
控制器中的代码:
连接字符串:
var node = new Uri("http://localhost:9200");
var settings = new ConnectionSettings(node);
settings.DisableDirectStreaming();
settings.DefaultIndex("extract");
var client = new ElasticClient(settings);
查询:
var query = (dynamic)null;
query = new MatchQuery
Field = "content",
Query = content,
Fuzziness = Fuzziness.Auto,
PrefixLength = 3,
MaxExpansions = 10
;
查询生成器
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 查询
我使用此代码来获取我在上面发布的查询。然后将此查询通过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 响应
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);
这就是问题所在。以上调试信息来自response
ElasticSearchJsonObject
我认为问题可能出在某个地方?该类是通过在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;
我确信这可以用来获得响应。
请注意,在简单搜索的情况下,此代码有效:
所以对于下面的这个查询,我的代码是有效的:
var request = new SearchRequest
From = 0,
Size = 20,
Query = query
;
【问题讨论】:
您是说 exact same 查询在 Kibana 中有效,但在 NEST 中无效? 是的,kibana 给出结果,但 NEST 没有。调试信息来自 NEST 您能否更新您的问题以提供一个简洁、可重复的示例?我不认为它们可以是 Kibana 和 NEST 中的完全相同查询。您可以从 Kibana 获取 JSON 并将其传递给低级客户端搜索方法以进行验证 我会更新剩余的代码和我的映射类。但是关于你的第二个问题,我正在接受 NEST 构建的精确查询,然后在控制台中在GET ExtractIndex/_Search
之后通过它并给出了结果。
没问题,很高兴你把它整理好了。我强烈建议阅读我上面链接到的文档,因为那里有很多有用的信息:)
【参考方案1】:
deep pagination 不建议使用 from/size,因为对于一个 deep page,需要从所有分片中获取大量文档,只能丢弃当最终返回一个整体有序的结果集时。此操作是 Elasticsearch 的分布式特性所固有的,并且在许多与深度分页相关的分布式系统中都很常见。
使用search_after
,您可以分页以无状态方式转发文档,这需要
_score
排序)
将来自一个搜索请求的命中中最后一个文档的排序字段的值作为"search_after": []
的值传递给下一个请求。
在使用后搜索文档中,搜索请求是按NumberOfCommits
降序排序,然后按Name
降序排序的。用于每个排序字段的值在SearchAfter(...)
中传递,分别是Project.First.NumberOfCommits
和Project.First.Name
属性的值。这告诉 Elasticsearch 返回具有与每个字段的排序约束相对应的排序字段的值的文档,并且与请求中提供的值相关。例如,对NumberOfCommits
提供的值为 775 的降序排序意味着 Elasticsearch 应该只考虑值小于 775 的文档(并对所有排序字段和提供的值执行此操作)。
如果您需要深入了解任何 NEST 文档,请单击页面上的 "EDIT"
链接:
它将带你到文档的 github 存储库,以及页面的原始 asciidoc 降价:
在该页面中将有一个链接返回到生成 asciidoc 的原始 NEST 源代码。在这种情况下,原始文件是SearchAfterUsageTests.cs in the 6.x branch
【讨论】:
你的回答确实帮助了我前进,但我又遇到了一个小问题,请你看看更新部分并指导我。 @Russ Cam 我在两个示例中都有编译错误:"Project" doesn't contain a definition for "First"
(Fluent DSL 或对象初始化程序)。另外,在对象初始化器中我也有错误:The non-generic type "Field" cannot be used with type arguments
。我错过了什么? @abdul qayyum 你成功了吗?以上是关于NEST Api SearchAfter 在 NEST 中返回 null 但在 Kibana 中有效的主要内容,如果未能解决你的问题,请参考以下文章
使用nest.js在AWS Lambda中获取Cognito数据(即requestContext)
如何在 Nest API iOS 中成功注销后重新加载登录页面
在 Nest.js 中,如何在我的 API 响应中提供与我的 JSON 对象捆绑在一起的静态内容文件