2

假设我启动并运行了一个 ElasticSearch 和 Blog 对象。

 public class Blog
 {
     [ElasticProperty(Name = "guid", Index = FieldIndexOption.NotAnalyzed, Type = FieldType.String)]
     public Guid? Guid { get; set; }

     [ElasticProperty(Name = "title", Index = FieldIndexOption.Analyzed, Type = FieldType.String)]
    public string Title { get; set; } = "";

     [ElasticProperty(Name = "body", Index = FieldIndexOption.Analyzed, Type = FieldType.String)]
     public string Body { get; set; } = "";

     [ElasticProperty(Name = "publishedDate", Index = FieldIndexOption.Analyzed, Type = FieldType.Date)]
     public DateTime PublishedDate { get; set; }
}

现在我只想将属性的一个子集返回到一个新类中

 public class BlogListItem
 {
       public static Expression<Func<Blog, object>> Selector = e => new BlogListItem
        {
            Title =  e.Title,
            PublishedDate = e.PublishedDate,
        };

        public string Title { get; set; }
        public DateTime PublishedDate { get; set; }
 }

通常我使用实体框架,我会在 BlogListItem 类中编写一个 Selector,但我发现很难找到任何关于在 ElasticSearch 中使用 NEST 执行此操作的信息

var res = elastic.Search<Blog>(s => s
           .From(0)
           .Size(3)
           .Index(blogIndex)
           .Query(q => q.MatchAll())
           .Sort(o => o.OnField(p => p.PublishedDate))
           .Fields(BlogListItem.Selector)
           );

  var result = res.Hits.Select(e => e.Source).ToList();

这将返回正确数量的命中,但源为空,我无法弄清楚在哪里可以找到返回的属性。

解决方案 1 我找到了一个替代解决方案,但如果这是一个好的解决方案,我想输入。

var res2 = elastic.Search<Blog, BlogListItem>(s => s
             .From(0)
             .Size(3)
             .Index(blogIndex)
             .Query(q => q.MatchAll())
             .Sort(o => o.OnField(p => p.PublishedDate))
             );

List<BlogListItem> resultList = res2.Hits.Select(hit => hit.Source).ToList();

这给了我返回的正确对象,但我对映射没有任何控制权,我不确定它是否返回所有属性然后进行映射。

解决方案 2.5 在这个解决方案中,我使用新的选择器更新了我的 BlogListItem。

    public class BlogListItem
    {
        public static SearchSourceDescriptor<Blog> Selector(SearchSourceDescriptor<Blog> sr)
        {
            return sr.Include(fi => fi.Add(f => f.Title));
        }

        [ElasticProperty(Name = "title")]        
        public string TitleNewName { get; set; }
        public DateTime PublishedDate { get; set; }
    }

然后是我的 elasticSearch 代码

var res3 = elastic.Search<Blog, BlogListItem>(s => s
                .From(0)
                .Size(3)
                .Index(blogIndex)
                .Query(q => q.MatchAll())
                .Sort(o => o.OnField(p => p.PublishedDate))                   
                .Source(BlogListItem.Selector)
                );

            List<BlogListItem> resultList = res3.Hits.Select(hit => hit.Source).ToList();

现在这限制了返回的属性,所以我只得到 Title 并且 PublishedDate 为空,我知道可以控制映射,这要归功于

[ElasticProperty(Name = "title")]

仍然需要验证这是否是使用 ElasticSearch 的正确方法。

这将产生以下 Json

{
  "from": 0,
  "size": 3,
  "sort": [
    {
      "publishedDate": {}
    }
  ],
  "_source": {
    "include": [
      "title"      
    ]
  },
  "query": {
    "match_all": {}
  }
}
4

1 回答 1

1

您的代码存在一些问题。

Using.Fields(BlogListItem.Selector)返回一个名为“publishedDate.title”的字段,这当然是错误的。我不确定如何使用Expression提及字段的语法,所以我不会尝试修复它。我通过打印请求 JSON 发现了这个错误。查看对 SO 上另一个问题的回答,了解如何通过打印请求 JSON 来调试 Nest 查询。也许您可以Expression使用这个技巧自己修复语法:)

Fields()我使用我最熟悉的语法进行了修复:

.Fields(f => f
    .Add(t => t.Title)
    .Add(t => t.PublishedDate)

即使使用此修复程序,您也会发现源是null. 我们来到下一个问题。如果您"fields"在搜索请求中提供选项,"_source"则不会出现在响应命中中。这是 Elasticsearch 的行为,与 Nest 无关。在这种情况下,您必须依靠Fields.FieldValuesDictionary而不是Source

var result = res.Hits.Select(e => e.Fields.FieldValuesDictionary).ToList();

然后您可以根据上面的结果构建BlogListItem对象。

于 2016-01-03T14:51:20.980 回答