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);

NEST 中的协变的更多相关文章

  1. 理解Java中的协变返回类型

    在面向对象程序设计中,协变返回类型指的是子类中的成员函数的返回值类型不必严格等同于父类中被重写的成员函数的返回值类型,而可以是更 "狭窄" 的类型. Java 5.0添加了对协变返 ...

  2. c++ 类覆盖方法中的协变返回类型

    c++ 类覆盖方法中的协变返回类型 在C++中,只要原来的返回类型是指向类的指针或引用,新的返回类型是指向派生类的指针或引用,覆盖的方法就可以改变返回类型.这样的类型称为协变返回类型(Covarian ...

  3. Scala中的协变,逆变,上界,下界等

    Scala中的协变,逆变,上界,下界等 目录 [−] Java中的协变和逆变 Scala的协变 Scala的逆变 下界lower bounds 上界upper bounds 综合协变,逆变,上界,下界 ...

  4. 编写高质量代码改善C#程序的157个建议——建议44:理解委托中的协变

    建议44:理解委托中的协变 委托中的泛型变量天然是部分支持协变的.为什么是“部分支持协变”?看下面示例: class Program { public delegate T GetEmployeeHa ...

  5. .net中的协变和逆变

    百度:委托中的协变和逆变. 百度:.net中的协变和逆变. 协变是从子类转为父类. 逆变是从父类到子类. 这样理解不一定严谨或者正确.需要具体看代码研究.

  6. Java泛型中的协变和逆变

    Java泛型中的协变和逆变 一般我们看Java泛型好像是不支持协变或逆变的,比如前面提到的List<Object>和List<String>之间是不可变的.但当我们在Java泛 ...

  7. C#4.0中的协变和逆变

    原文地址 谈谈.Net中的协变和逆变 关于协变和逆变要从面向对象继承说起.继承关系是指子类和父类之间的关系:子类从父类继承所以子类的实例也就是父类的实例.比如说Animal是父类,Dog是从Anima ...

  8. java interface和class中的协变

    协变 Java中的协变是指,当发生继承时,子类中重写父类的方法时,可以返回父类方法返回类型的子类型.比如: class SuperClass{} class SubClass extends Supe ...

  9. C# 中的协变和逆变

    作为一个从接触 Unity 3D 才开始学习 C# 的人,我一直只了解一些最基本.最简单的语言特性.最近看了<C# in Depth>这本书,发现这里面东西还真不少,即使除去和 Windo ...

随机推荐

  1. nginx转发tomcat请求转成https后页面不能下载apk文件而是直接打开

    访问域名下面的apk文件 https://xxxx/xxx.apk 浏览器没有下载而是直接打开了文件 没有找到问题原因,可能是https的原因,要是用http就可以下载,转发https就有问题 后来是 ...

  2. DDOS学习笔记(《破坏之王-DDOS攻击与防范深度剖析》)

           最近花了点时间把<破坏之王-DDOS攻击与防范深度剖析>看了一遍,坦白来说,这本书比较浅显,可以说是入门书,当然对于我这种对DDOS一知半解的人来说,也是一本不错的书,起码我 ...

  3. 你的Excel表格颜色搭配的对么?

    在昨天的文章中,我们讨论了<Excel表格制作的基本九大原则>,今天我们还要继续聊聊,Excel表格的颜色搭配规则. 一个表格的美丑与否,除了基本的格式之外,如何配色也是非常关键的,如果只 ...

  4. JAVA中的集合与排序

    一:常见的集合类 Collection接口  和   Map接口 Collection ①:collection是最常见的集合的上级接口. ②:继承自collection的常用接口有List,Set, ...

  5. 为了CET-4!

    Directions For tiis part,you are allowed 30 minutes to write an essay.Suppose there are two options ...

  6. 绝世emacs配置for Ubuntu

    反正过不了几天就要退役了,把emacs配置放出来造福(祸害)大众? 浓浓的OIER风格,除了方便打代码就没别的用处(F8并不这样认为?),只可惜windows下的弄丢了,只有Ubuntu下的. F1不 ...

  7. Java中堆与栈

    简单的说:Java把内存划分成两种:一种是栈内存,一种是堆内存. 1:什么是堆内存: 堆内存是是Java内存中的一种,它的作用是用于存储Java中的对象和数组,当我们new一个对象或者创建一个数组的时 ...

  8. 聊聊API网关的作用

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 10.5px "Trebuchet MS" } p.p2 { margin: 0.0px ...

  9. java调优(一)

  10. APP网络测试要点和弱网模拟

    当前APP网络环境比较复杂,网络制式有2G.3G.4G网络,还有越来越多的公共Wi-Fi.不同的网络环境和网络制式的差异,都会对用户使用app造成一定影响.另外,当前app使用场景多变,如进地铁.上公 ...