扩展复杂对象的 BSON `$type` 属性?

Extending BSON `$type` attribute for complex object?

我正在尝试将对象存储在 MongoDB 中。该对象来自第三方系统,具有非常特定的格式,即所有对象属性都存储在字典中。此字典中的值可以是不同类型且没有特定顺序。

我相信要有效地搜索这些字段,我需要将它们转换为 BSON 属性。它可以使用自定义序列化器/反序列化器,直到涉及到反序列化本身。如果 属性 是一个表示为 BSON 文档的复杂对象,自定义解串器不知道应该将此文档转换为哪种类型。

如何使用 MongoDB BSON 以正确的方式解决此类问题?

我会在复杂文档中添加新的 属性 $type,并在序列化期间将目标类型存储在那里,但它会干扰构建 MongoDB $type 属性.

是否可以同时使用标准和自定义 $type 属性?在这种情况下,实现自定义解串器的最佳实践方法是什么?

并非没有扩展规范本身或在文档本身中包含一些关于如何(反)序列化规范的参考。

PHP 驱动程序有一个 ODM 框架,完全 您所提议的。我建议你看看 http://php.net/manual/en/class.mongodb-bson-persistable.php

During serialization, the driver will inject a __pclass property containing the PHP class name into the data

因此,它会在要存储的文档中添加一个特定的键“__pclass”。在反序列化过程中,驱动程序从密钥中读取以决定采取哪些具体的反序列化步骤,并在 returns 文档之前剥离 __pclass key/value (现在反序列化为任何 PHP class 由 __pclass 键指定)给用户。

如果您有任何理由不信任 mongodb 中保存的数据,这将非常危险。它基本上允许数据指示对可执行 PHP 代码的调用。

关于规范本身。 http://bsonspec.org/spec.html

类型及其关联的类型索引已硬编码到规范中。

element     ::=     "\x01" e_name double    64-bit binary floating point
    |   "\x02" e_name string    UTF-8 string
    |   "\x03" e_name document  Embedded document
    |   "\x04" e_name document  Array
    |   "\x05" e_name binary    Binary data
    |   "\x06" e_name   Undefined (value) — Deprecated
    |   "\x07" e_name (byte*12)     ObjectId
    |   "\x08" e_name "\x00"    Boolean "false"
    |   "\x08" e_name "\x01"    Boolean "true"
    |   "\x09" e_name int64     UTC datetime
    |   "\x0A" e_name   Null value
    |   "\x0B" e_name cstring cstring   Regular expression - The first cstring is the regex pattern, the second is the regex options string. Options are identified by characters, which must be stored in alphabetical order. Valid options are 'i' for case insensitive matching, 'm' for multiline matching, 'x' for verbose mode, 'l' to make \w, \W, etc. locale dependent, 's' for dotall mode ('.' matches everything), and 'u' to make \w, \W, etc. match unicode.
    |   "\x0C" e_name string (byte*12)  DBPointer — Deprecated
    |   "\x0D" e_name string    JavaScript code
    |   "\x0E" e_name string    Symbol. Deprecated
    |   "\x0F" e_name code_w_s  JavaScript code w/ scope
    |   "\x10" e_name int32     32-bit integer
    |   "\x11" e_name uint64    Timestamp
    |   "\x12" e_name int64     64-bit integer
    |   "\x13" e_name decimal128    128-bit decimal floating point
    |   "\xFF" e_name   Min key
    |   "\x7F" e_name   Max key

如果您使用用户定义的子类型范围将 blob 存储在二进制块中,则可以创建您自己的用户生成的二进制子类型。

binary  ::=     int32 **subtype** (byte*)   Binary - The int32 is the number of bytes in the (byte*).

subtype     ::=     "\x00"  Generic binary subtype
    |   "\x01"  Function
    |   "\x02"  Binary (Old)
    |   "\x03"  UUID (Old)
    |   "\x04"  UUID
    |   "\x05"  MD5
    |   **"\x80"    User defined**

不利的一面是该对象将作为二进制 blob 存储在数据库中,这使得除了子类型检查之外的查询变得非常困难。

除此之外的任何内容都将涉及扩展规范本身