我们在应用程序中使用弹性搜索仅用于文档搜索,因此我们没有任何一位专家。我成功地使用了TermQuery
,SimpleQueryStringQuery
和MatchPhraseQuery
。但我在文档中发现使用From
& Size
分页不适合制作,建议使用Search After。
但我的实现返回null
。令我感到困惑的是<Project>
参数中的内容应该如Nest API Object Initializer
语法in docs here中所示。
我的代码如下所示:
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
仅用于测试以及_id
中的硬代码SearchAfter
值。
NEST生成的查询是:
{
"size": 1,
"sort": [
{
"_id": {
"order": "desc"
}
}
],
"search_after": [
"0fc3ccb625f5d95b973ce1462b9f7"
],
"query": {
"match": {
"content": {
"query": "lahore",
"fuzziness": "AUTO",
"prefix_length": 3,
"max_expansions": 10
}
}
}
}
来自ES的回复确实说成功但没有返回结果。
TrackScores = 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
};
答案 0 :(得分:1)
深度分页不建议使用from / size,因为需要从深层页面的所有分片中提取文档数量,只能被丢弃当最终返回整体有序结果集时。此操作是Elasticsearch的分布式特性所固有的,并且与深度分页相关的许多分布式系统都很常见。
使用search_after
,您可以分页以无状态方式转发文档,并且需要
_score
排序)"search_after": []
的值传递给下一个请求。在“搜索使用后”文档中,搜索请求的排序方式为NumberOfCommits
降序,然后按Name
降序排序。用于每个排序字段的值分别在SearchAfter(...)
中传递,分别是Project.First.NumberOfCommits
和Project.First.Name
属性的值。这告诉Elasticsearch返回具有与每个字段的排序约束对应的排序字段的值的文档,并且与请求中提供的值相关。例如,使用提供的值775对NumberOfCommits
进行降序排序意味着Elasticsearch应该只考虑值小于775的文档(并且对所有排序字段和提供的值执行此操作)。
如果您需要深入了解任何NEST文档,请点击页面上的"EDIT"
链接:
将带您到文档的github存储库,页面的原始asciidoc markdown:
在该页面中将链接回原始NEST源代码,从中生成asciidoc。在这种情况下,原始文件为SearchAfterUsageTests.cs in the 6.x branch