首页 技术 正文
技术 2022年11月8日
0 收藏 902 点赞 1,911 浏览 3338 个字

Convariant search results

version 5.x

NEST 直接支持返回协变结果集合。这意味着,可以将搜索结果的类型指定为一个接口或者基类,但是其真实类型仍然是接口或基类的一个子类型。

让我们来看一个例子,假设我们想要搜索的多个类型都实现了 ISearchResult 接口

public interface ISearchResult
{
string Name { get; set; }
}public abstract class BaseX : ISearchResult
{
public string Name { get; set; }
}

针对 ISearchResult ,我们提供了三种实现,分别叫 A, BC

public class A : BaseX
{
public int PropertyOnA { get; set; }
}public class B : BaseX
{
public int PropertyOnB { get; set; }
}public class C : BaseX
{
public int PropertyOnC { get; set; }
}

使用 Types

要想搜索多个类型,最直接的方式是,先将响应的类型指定为接口或者基类,然后使用 .Type() 传递我们想搜索的实际类型

var result = this._client.Search<ISearchResult>(s => s
.Type(Types.Type(typeof(A), typeof(B), typeof(C)))
.Size(100)
);

NEST 会把这份逻辑代码转化为 /index/a,b,c/_search ,有 "_type" : "a" 的命中结果会被序列化为 A 类型的对象,以此类推。

在这里,我们假设所有的响应都是有效的,并且我们将接收到预期的 100 份文档。记住, result.Document 是一个 IReadOnlyCollection<ISearchResult> 类型的对象

result.ShouldBeValid();
result.Documents.Count.Should().Be(100);

为了证明返回的结果集合是协变的,我们根据它们的真实类型过滤文档,并断言这些子集是我们期望的大小

var aDocuments = result.Documents.OfType<A>();
var bDocuments = result.Documents.OfType<B>();
var cDocuments = result.Documents.OfType<C>();aDocuments.Count().Should().Be(25);
bDocuments.Count().Should().Be(25);
cDocuments.Count().Should().Be(50);

另外,假设只存在于子类本身的属性会被正确填充

aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0);
bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0);
cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0);

使用 ConcreteTypeSelector

一个相对较低级别的方式是,自己检查命中结果,并确定要反序列化的 CLR 类型

var result = this._client.Search<ISearchResult>(s => s
.ConcreteTypeSelector((d, h) => h.Type == "a" ? typeof(A) : h.Type == "b" ? typeof(B) : typeof(C))
.Size(100)
);

对于每一个命中结果,我们会调用传递给 ConcreteTypeSelector 的委托

  • d 表示 _source 公开为一个 dynamic 类型
  • 带有类型的 h 代表着对命中结果的封装(例如:Hit<dynamic>

我们假设响应是有效的,并且接收到了预期的 100 份文档。记住, result.Document 是一个 IReadOnlyCollection<ISearchResult> 类型的对象

result.ShouldBeValid();
result.Documents.Count.Should().Be(100);

为了证明返回的结果集合是协变的,我们根据它们的真实类型过滤文档,并断言这些子集是我们期望的大小

var aDocuments = result.Documents.OfType<A>();
var bDocuments = result.Documents.OfType<B>();
var cDocuments = result.Documents.OfType<C>();aDocuments.Count().Should().Be(25);
bDocuments.Count().Should().Be(25);
cDocuments.Count().Should().Be(50);

另外,假设只存在于子类本身的属性会被正确填充

aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0);
bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0);
cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0);

使用 CovariantTypes

Scroll API 是上一个搜索示例的延伸,我们不再使用 Types() 。你可以使用 .CovariantTypes() 来指示类型。

var result = this._client.Scroll<ISearchResult>(TimeSpan.FromMinutes(60), "scrollId", s => s
.CovariantTypes(Types.Type(typeof(A), typeof(B), typeof(C)))
);

NEST 会把这份逻辑代码转化为 /index/a,b,c/_search ,有 "_type" : "a" 的命中结果会被序列化为 A 类型的对象,以此类推。

后续的验证过程同上(也许你已经发现前面的两节内容里存在者相同的步骤)

相对较低级别的 concrete type selector 也可以用在 scroll 中

var result = this._client.Scroll<ISearchResult>(TimeSpan.FromMinutes(1), "scrollid", s => s
.ConcreteTypeSelector((d, h) => h.Type == "a" ? typeof(A) : h.Type == "b" ? typeof(B) : typeof(C))
);

重复验证工作

协变不仅仅在接口方式中工作,下面便是子类型协变的示例:

var result = this._client.Search<BaseX>(s => s
.Type(Types.Type(typeof(A), typeof(B), typeof(C)))
.Size(100)
);
result.ShouldBeValid();
result.Documents.Count.Should().Be(100);var aDocuments = result.Documents.OfType<A>();
var bDocuments = result.Documents.OfType<B>();
var cDocuments = result.Documents.OfType<C>();aDocuments.Count().Should().Be(25);
bDocuments.Count().Should().Be(25);
cDocuments.Count().Should().Be(50);aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0);
bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0);
cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0);
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,491
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,907
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,740
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,493
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,132
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,294