ant*_*123 6 c# mongodb deserialization
我有以下课程:
[BsonIgnoreExtraElements]
public class WidgetCollection
{
[BsonId]
public int AccountId { get; set; }
public ReadOnlyCollection<Widget> Widgets { get; set; }
}
[BsonIgnoreExtraElements]
[BsonDiscriminator(RootClass = true)]
[BsonKnownTypes(typeof(OtherObject1), ...)]
public class Widget
{
public ObjectId Id { get; set; }
public string Title { get; set; }
public int Position { get; set; }
public WidgetKind Kind { get; set; }
public bool IsActive { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
DB中此实例的示例:
{ "_id" : 2993644, "Widgets" : [ { "_t" : "Widget", "_id" : ObjectId("504797b327e10b1e80c838ac"), "Title" : "My Notes", "Position" : 1, "Kind" : 0, "IsActive" : true } ] }
Run Code Online (Sandbox Code Playgroud)
然后我有一个聚合命令,过滤掉"Widgets"数组中的元素,只返回"IsActive"为true的元素.在这种情况下,该命令只返回整个对象.
var command = new CommandDocument
{
{"aggregate", "myCollection" },
{"pipeline", commandArray }
};
var result = database.RunCommandAs<AggregateResult<WidgetCollection>>(command).Result;
return result;
Run Code Online (Sandbox Code Playgroud)
这是AggregateResult类:
public class AggregateResult<T> : CommandResult
{
public T Result
{
get
{
var result = Response["result"].AsBsonArray.SingleOrDefault().AsBsonDocument;
return BsonSerializer.Deserialize<T>(result);
}
}
}
Run Code Online (Sandbox Code Playgroud)
是的,我知道SingleOrDefault().AsBsonDocument可能会出现NRE,但现在不是问题.我已经调试了代码直到反序列化,并验证了"result"变量包含与上面显示的完全相同的BSON.尝试反序列化结果时收到此消息:"反序列化类Community.Widgets.WidgetCollection的Widgets属性时发生错误:预期元素名称为'_v',而不是'_id'".
为什么解串器期望'_v'元素?
更新
我通过更改Widgets属性的类型来修复上述问题ICollection.我现在收到这个错误:Unknown discriminator value 'Widget'.对我来说,这没有任何意义,因为doc有"_t" : "Widget"元素.
我也试过插入一个派生类,之后"_t"元素的值现在"[ "Widget", "DerivedClass"]正如预期的那样,我得到了同样的错误.同样,database.FindOneAs<>()只有在明确使用时才会发生这种情况BsonSerializer.Deserialize<>().我在调用之前尝试添加此代码Deserialize():
BsonClassMap.RegisterClassMap<Widget>(cm => { cm.AutoMap(); cm.SetIsRootClass(true); });
BsonClassMap.RegisterClassMap<RssFeedWidget>();
Run Code Online (Sandbox Code Playgroud)
但我不确定初始化代码应该去哪里,我认为如果我在我的类上使用鉴别器属性则不需要它.
这是我的聚合命令
BsonDocument documentMatch = new BsonDocument{{"$match", new BsonDocument{{"_id", documentId}}}};
BsonDocument unwindArray = new BsonDocument{{"$unwind", "$Widgets"}};
BsonDocument arrayMatch = new BsonDocument{{"$match", new BsonDocument{{"Widgets.IsActive", true}}}});
BsonArray commandArray = new BsonArray();
commandArray.Add(documentMatch);
commandArray.Add(unwindArray),
commandArray.Add(arrayMatch);
var command = new CommandDocument
{
{"aggregate", collectionName},
{"pipeline", commandArray}
}
var result = database.RunCommandAs<AggregateResult<WidgetCollection>>(command).Result;
Run Code Online (Sandbox Code Playgroud)
我无法重现这个问题。我使用了下面的程序。因此,由于我在这里使用相对简单的管道,也许您的问题是映射后聚合文档没有返回。你能发布你的聚合命令吗?
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace TestConsole_Source
{
class Program
{
[BsonIgnoreExtraElements]
public class WidgetCollection
{
[BsonId]
public int AccountId { get; set; }
public ReadOnlyCollection<Widget> Widgets { get; set; }
}
[BsonIgnoreExtraElements]
[BsonDiscriminator(RootClass = true)]
public class Widget
{
public string Title { get; set; }
public int Position { get; set; }
public bool IsActive { get; set; }
}
static void Main(string[] args)
{
var server = MongoServer.Create();
server.Connect();
var db = server.GetDatabase("widgettest");
var collection = db.GetCollection<WidgetCollection>("widgets");
collection.Drop();
var widgets = new WidgetCollection();
var widget1 = new Widget { Title = "One", Position = 0, IsActive = true };
var widget2 = new Widget { Title = "Two", Position = 1, IsActive = true };
var widget3 = new Widget { Title = "Three", Position = 2, IsActive = false };
widgets.Widgets = new List<Widget> { widget1, widget2, widget3 }.AsReadOnly();
collection.Save(widgets);
var command = new CommandDocument(
new BsonElement("aggregate", "widgets"),
new BsonElement("pipeline", new BsonArray(new [] {
new BsonDocument(
new BsonElement("$project", new BsonDocument("Widgets", 1)))})));
var response = db.RunCommand(command);
var rawDoc = response.Response["result"].AsBsonArray.SingleOrDefault().AsBsonDocument;
var doc = BsonSerializer.Deserialize<WidgetCollection>(rawDoc);
//Console.ReadKey();
}
}
}
Run Code Online (Sandbox Code Playgroud)
更新: 使用上面的新信息,我已更正您的聚合查询以使其正常工作。您需要使用一个组才能将结果恢复为与驱动程序期望的格式相同的格式。
var command = new CommandDocument(
new BsonElement("aggregate", "widgets"),
new BsonElement("pipeline", new BsonArray(new[] {
new BsonDocument(
new BsonElement("$unwind", "$Widgets")),
new BsonDocument(
new BsonElement("$match", new BsonDocument("Widgets.IsActive", true))),
new BsonDocument(
new BsonElement("$group", new BsonDocument(
new BsonElement("_id", "$_id"),
new BsonElement("Widgets", new BsonDocument("$addToSet", "$Widgets")))))})));
Run Code Online (Sandbox Code Playgroud)
即使这可行,我仍然建议不要执行此过程并简单地过滤小部件客户端。
| 归档时间: |
|
| 查看次数: |
6174 次 |
| 最近记录: |