【问题标题】:Mass filtering with protobuf-net使用 protobuf-net 进行质量过滤
【发布时间】:2011-02-14 19:09:07
【问题描述】:

我已经用 protobuf-net 序列化了一个对象列表。

理论上,.bin 文件可以包含数百万个对象。

假设对象属于包含以下内容的类:

public string EventName;

我必须进行查询并创建一个包含与查询匹配的对象的列表。 使用 LINQ 从序列化文件中提取匹配对象的正确方法是什么?

【问题讨论】:

    标签: c# .net protobuf-net


    【解决方案1】:

    protobuf 格式是项的线性序列;您使用的任何索引等只能单独应用。但是,IEnumerable<T> 可用;你可能会发现:

    var item = Serializer.DeserializeItems<YourType>(source)
           .First(item => item.Id == id);
    

    做得很好;这个:

    • 被懒惰地假脱机;每个项目都是单独生成的,因此您不需要过多的内存
    • 短路;如果在起点附近找到该项目,它将立即退出

    或者对于多个项目:

    var list = Serializer.DeserializeItems<YourType>(source)
        .Where(item => item.Foo == foo);
    

    (如果您想在内存中缓冲匹配项,则在上面的末尾添加一个 ToList,如果您只想以仅转发的方式解析一次,则使用不使用 ToList)

    【讨论】:

    • 我觉得这个解决方案不错,但是代码应该能够提取出一些匹配查询的对象。
    • 非常感谢,马克 :)。再次。我应该在 DeserializeItems 方法中作为“标签”的参数传递什么?
    • 我做到了。我应该在 deserializeItems 方法中传递什么标签?
    • @Gilad - Serializer.ListItemTag(实际上只是 1) - 前缀样式为 base-128(但无论如何这是默认值)
    【解决方案2】:

    如果你想在选定的元素列表上添加一些投影,你应该试试我的库,https://github.com/Scooletz/protobuf-linq。它们也可在 NuGet 上使用。 该库大大降低了反序列化的开销。在某些情况下,它可能会下降到原始查询的 50%。

    【讨论】:

      【解决方案3】:

      很遗憾,没有。为了使用 LINQ,您的对象必须实现 IQueryable&lt;T&gt;IEnumerable&lt;T&gt;。除非有 LINQ 提供程序可以在您的 .bin 文件中提供 IQueryable&lt;T&gt; 接口,否则您必须:

      • 将文件反序列化到内存中并使用 LINQ-to-objects IEnumerable&lt;T&gt;
      • 编写可以提供IQueryable&lt;T&gt; 的 LINQ 提供程序(如果您的文件很大,这可能是唯一实用的选择),可以在不加载整个文件的情况下处理文件。

      【讨论】:

      • 很好,DeserializeItems 提供了一个IEnumerable&lt;T&gt; API,那么
      • @Marc:看起来是这样!我曾假设反序列化会将整个文件加载到内存中。显然我错了。
      • 它会懒惰地从流中假脱机 (yield return) - 非常适合处理大量数据
      【解决方案4】:

      protobuf 可以将文件内容作为流IEnumerable&lt;T&gt; 提供给您,因此您可以轻松做到这一点。不幸的是,我不知道该方法是如何调用的,但在文档中很容易找到。

      【讨论】:

      • @Marc 我应该如何序列化项目以使用 DeserializeItems?你有一个简单的例子吗?我一直试图在 V2 中做到这一点。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-24
      • 2015-12-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多