【问题标题】:MongoDB - Inserting a document with $type causes exceptionMongoDB - 使用 $type 插入文档会导致异常
【发布时间】:2014-05-13 15:59:33
【问题描述】:

当我尝试插入以下文档时,MongoDB 抛出错误:

{
  "dt": "2014-05-13 02:43:01.454",
  "ev": "coredatasaveform",
  "ci": "rQBDXUAbSqy8BP3ZuOXWVg==",
  "mi": "Hw5ySHcJSO+HKxBD1s4zQA==",
  "on": "Company",
  "json": {
    "_id": {
      "$type": "03",
      "$binary": "O1tFU+smDEGo/v/hB1/giw=="
    },
    "_lastmodifieddatelocalutc": "2014-05-13 02:43:01",
    "name": "A company name here",
    "_lastmodifiedonservertime": {
      "$date": 1398876087000
    },
    "_zv": "1.8",
    "_mi": "Hw5ySHcJSO+HKxBD1s4zQA==",
    "sourceofdata": "xxxccc"
  },
  "na": "HPSDbUtilities persistCapturedModelValuesSetWithModel (null)",
  "rc": "1"
}

错误如下所示:

03:44:02.0421 WriteMongoDocument Exception was :Element name '$type' is not valid because it starts with a '$'.    at MongoDB.Bson.IO.BsonWriter.CheckElementName(String name)
   at MongoDB.Bson.IO.BsonWriter.WriteName(String name)
   at MongoDB.Bson.Serialization.Serializers.BsonDocumentSerializer.Serialize(BsonWriter bsonWriter, Type nominalType, Object value, IBsonSerializationOptions options)
   at MongoDB.Bson.Serialization.Serializers.BsonValueSerializer.Serialize(BsonWriter bsonWriter, Type nominalType, Object value, IBsonSerializationOptions options)
   at MongoDB.Bson.Serialization.Serializers.BsonDocumentSerializer.Serialize(BsonWriter bsonWriter, Type nominalType, Object value, IBsonSerializationOptions options)
   at MongoDB.Bson.Serialization.Serializers.BsonValueSerializer.Serialize(BsonWriter bsonWriter, Type nominalType, Object value, IBsonSerializationOptions options)
   at MongoDB.Bson.Serialization.Serializers.BsonDocumentSerializer.Serialize(BsonWriter bsonWriter, Type nominalType, Object value, IBsonSerializationOptions options)
   at MongoDB.Driver.Internal.MongoInsertMessage.AddDocument(BsonBuffer buffer, Type nominalType, Object document)
   at MongoDB.Driver.Operations.InsertOperation.Execute(MongoConnection connection)
   at MongoDB.Driver.MongoCollection.InsertBatch(Type nominalType, IEnumerable documents, MongoInsertOptions options)
   at MongoDB.Driver.MongoCollection.Insert(Type nominalType, Object document, MongoInsertOptions options)
   at MongoDB.Driver.MongoCollection.Insert(Type nominalType, Object document)
   at MongoDB.Driver.MongoCollection.Insert[TNominalType](TNominalType document)
   at Tradeshow.Models.Mongo.WriteMongoLogDocument(String rawJSON, Int32 ix) in C:\Inetpub\wwwroot\Tradeshow\Tradeshow\Models\Mongo.cs:line 665

代码如下所示:

BsonDocument document = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>(rawJSON);
collection.Insert(document);

但是,如果我在“json”元素中转置“_id”元素的“$type”和“$binary”元素,那么 Mongo 很乐意插入文档。所以,这行得通:

{
  "dt": "2014-05-13 02:43:01.454",
  "ev": "coredatasaveform",
  "ci": "rQBDXUAbSqy8BP3ZuOXWVg==",
  "mi": "Hw5ySHcJSO+HKxBD1s4zQA==",
  "on": "Company",
  "json": {
    "_id": {
      "$binary": "O1tFU+smDEGo/v/hB1/giw=="
      ,"$type": "03"
    },
    "_lastmodifieddatelocalutc": "2014-05-13 02:43:01",
    "name": "A company name here",
    "_lastmodifiedonservertime": {
      "$date": 1398876087000
    },
    "_zv": "1.8",
    "_mi": "Hw5ySHcJSO+HKxBD1s4zQA==",
    "sourceofdata": "xxxccc"
  },
  "na": "HPSDbUtilities persistCapturedModelValuesSetWithModel (null)",
  "rc": "1"
}

JSON 文档是由一个稍微超出我控制范围的系统创建的,因此让 Mongo 接受第一个版本比尝试更改 JSON 的格式要容易得多。

谁能解释为什么第一个版本失败但第二个版本有效,以及如何让第二个版本正常工作?

我正在使用官方的 MongoDB C# 驱动程序 (v1.8.3.9)。

非常感谢

【问题讨论】:

  • 是否有理由需要一个名为 $type 的字段?我猜它不喜欢它,因为有一个关键字$type 而没有关键字$binary。所以在内部,我猜,它首先扫描关键字,然后忽略后面对象字段的关键字。
  • documentation,The field names cannot start with the dollar sign ($) character.所示 但问题很好,它是如何工作的?
  • 你确定它有效吗?我在我的 mongoshell 中进行了相同的测试,并且两者都有相同的错误。可能是驱动程序的错误...您可以在您的文档上执行 findOne 吗?
  • 给出了一个答案,说明为什么会这样,尽管您可能已经错过了。这是支持扩展 JSON 语法的驱动程序的一个特性。

标签: c# json mongodb


【解决方案1】:

这里的问题是,这实际上是 MongoDB 的 extended JSON syntax 的一部分,它实际上在 C# 驱动程序的 JSON Utils 中得到支持。

directly in the documentation所示,当字段以正确的顺序显示时:

"_id": {
  "$binary": "O1tFU+smDEGo/v/hB1/giw==",
  "$type": "03"
}

然后实际值将被转换为内部 BSON 表示中的 BinData 类型的字段。

由于 JSON 和 BSON 维护键值的顺序,因此如果它们实际上颠倒过来,它们的呈现顺序将导致问题。

这就是你的错误的来源。

您可能会查看此数据的一些初步解析,或者在直接将其他数据传递给 JSON utils 函数以将其直接解析为 BSON 之前找到一种操作数据块的方法。

仅供参考,您甚至可以在驱动程序源代码的unit tests 中看到这一点。

【讨论】:

    猜你喜欢
    • 2017-07-01
    • 2018-03-24
    • 1970-01-01
    • 2013-11-11
    • 1970-01-01
    • 2018-11-26
    • 1970-01-01
    • 2016-10-20
    • 1970-01-01
    相关资源
    最近更新 更多