根据特定子类型类型的元素匹配查找 MongoDB 文档
Find a MongoDB document based on element match of a specific subtype type
我正在使用 Mongo C# 驱动程序版本 2.2.3 连接到 Mongo 3.0.6 服务器。
给定 MongoDb 人 class 的集合(见下文)我想找到电子邮件地址为 "not@home.com" 的人。有点天真,我曾希望像这样的东西会起作用:
var people = database.GetCollection<Person>("People");
var person = from p in people.AsQueryable()
where p.Addresses.OfType<EmailAddress>().Any(e=>e.MailTo == "not@home.com")
但是在运行时,我收到 NotSupportedException
。表达式树不支持 OfType 方法。
是否有一种简单的方法来元素匹配(使用强类型)多态数组?
(这是模型)
class Person
{
public Address[] Addresses {get;set;}
}
class Address
{
}
class Phone : Address
{
public string Number {get;set;}
}
class Email : Address
{
public string MailTo {get;set;}
}
我要查找的示例文档是:
{
"_id" : ObjectId("56d76465b27c42eb491aa2e7"),
"Addresses" : [
{
"_t" : "Email",
"MailTo" : "not@home.com"
},
{
"_t" : "Phone",
"Number" : "555-1234"
}
]
}
好吧,虽然 C# 驱动程序没有完全实现并且缺少很多功能,但我认为问题出在您的 class 结构中。
例如一个 Person 对象将有地址,地址可能是 Phone 或 Email 类型,甚至两者兼而有之。这就是驱动程序抱怨的地方,因为它无法理解可能存在的对象类型。
因为它本质上更动态,所以我建议您使用 BsonDocument 类型来查询,而不是类型转换为您想要的任何对象。表示您获得结果的选项很少
选项#1:
如果执行以下代码:
var mailTo = "not@home.com";
var filter = Builders<BsonDocument>.Filter.ElemMatch("Addresses",
Builders<BsonDocument>.Filter.Eq("MailTo", mailTo));
var people = database.GetCollection<BsonDocument>("People");
var person = people.FindSync(filter).ToList();
您将在子文档中获得包含 not@hotme.com
的记录。
选项#2:
如果您可以稍微更改模型,则可以充分利用 linq 查询。
public class Person
{
public ObjectId Id { get; set; }
public Address[] Addresses { get; set; }
}
public class Address
{
public string MailTo { get; set; }
public string Number { get; set; }
}
var mailTo = "not@home.com";
var filter = Builders<Person>.Filter.ElemMatch(e => e.Addresses,
address => address.MailTo == mailTo );
var people = database.GetCollection<Person>("People");
var person = people.FindSync<Person>(filter).ToList();
现在 person 将拥有一个或多个符合您条件的 Person 对象。
你好,这在 2.2.4 中已经修复
请参阅 mongodb jira entry
我正在使用 Mongo C# 驱动程序版本 2.2.3 连接到 Mongo 3.0.6 服务器。
给定 MongoDb 人 class 的集合(见下文)我想找到电子邮件地址为 "not@home.com" 的人。有点天真,我曾希望像这样的东西会起作用:
var people = database.GetCollection<Person>("People");
var person = from p in people.AsQueryable()
where p.Addresses.OfType<EmailAddress>().Any(e=>e.MailTo == "not@home.com")
但是在运行时,我收到 NotSupportedException
。表达式树不支持 OfType 方法。
是否有一种简单的方法来元素匹配(使用强类型)多态数组?
(这是模型)
class Person
{
public Address[] Addresses {get;set;}
}
class Address
{
}
class Phone : Address
{
public string Number {get;set;}
}
class Email : Address
{
public string MailTo {get;set;}
}
我要查找的示例文档是:
{
"_id" : ObjectId("56d76465b27c42eb491aa2e7"),
"Addresses" : [
{
"_t" : "Email",
"MailTo" : "not@home.com"
},
{
"_t" : "Phone",
"Number" : "555-1234"
}
]
}
好吧,虽然 C# 驱动程序没有完全实现并且缺少很多功能,但我认为问题出在您的 class 结构中。
例如一个 Person 对象将有地址,地址可能是 Phone 或 Email 类型,甚至两者兼而有之。这就是驱动程序抱怨的地方,因为它无法理解可能存在的对象类型。
因为它本质上更动态,所以我建议您使用 BsonDocument 类型来查询,而不是类型转换为您想要的任何对象。表示您获得结果的选项很少
选项#1:
如果执行以下代码:
var mailTo = "not@home.com";
var filter = Builders<BsonDocument>.Filter.ElemMatch("Addresses",
Builders<BsonDocument>.Filter.Eq("MailTo", mailTo));
var people = database.GetCollection<BsonDocument>("People");
var person = people.FindSync(filter).ToList();
您将在子文档中获得包含 not@hotme.com
的记录。
选项#2:
如果您可以稍微更改模型,则可以充分利用 linq 查询。
public class Person
{
public ObjectId Id { get; set; }
public Address[] Addresses { get; set; }
}
public class Address
{
public string MailTo { get; set; }
public string Number { get; set; }
}
var mailTo = "not@home.com";
var filter = Builders<Person>.Filter.ElemMatch(e => e.Addresses,
address => address.MailTo == mailTo );
var people = database.GetCollection<Person>("People");
var person = people.FindSync<Person>(filter).ToList();
现在 person 将拥有一个或多个符合您条件的 Person 对象。
你好,这在 2.2.4 中已经修复 请参阅 mongodb jira entry