我正在尝试在MongoDB中存储对象。此对象来自第三方系统,并且具有非常特定的格式,即所有对象属性都存储在字典中。此词典中的值可以是不同类型,也不是特定顺序。
我相信要有效地搜索这些字段,我需要将它们转换为BSON属性。并且它可以使用自定义序列化器/解串器,直到它反序列化本身。如果property是一个复杂的对象,表示为BSON文档,则自定义deseriazer不知道该文档应该转换为哪种类型。
如何使用MongoDB BSON以正确的方式解决这类问题?
我会将新属性$type
添加到复杂文档中,并在序列化期间存储目标类型,但它会干扰MongoDB $type
属性中的构建。
是否可以并排使用标准和自定义$type
属性?在这种情况下,实现自定义反序列化器的最佳实践方法是什么?
答案 0 :(得分:1)
不是没有扩展规范本身,也不包括对文档本身应如何(de)序列化的一些引用。
PHP驱动程序有一个ODM框架,可以完全你提出的建议。我建议你看一下http://php.net/manual/en/class.mongodb-bson-persistable.php
在序列化期间,驱动程序将注入__pclass属性 将PHP类名称包含在数据中
因此,它将特定的键“__pclass”添加到要存储的文档中。在反序列化期间,驱动程序从键中读取以决定要采取的特定反序列化步骤,并在将文档(现在反序列化为__pclass键指定的任何PHP类)返回给用户之前删除__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存储在数据库中,因此在子类型检查之外进行查询非常困难。
除此之外的任何事情都涉及扩展规范本身