根据特定子类型的元素匹配查找MongoDB文档

时间:2016-03-02 21:10:25

标签: mongodb mongodb-.net-driver

我使用连接到Mongo 3.0.6服务器的Mongo C#驱动程序版本2.2.3。

鉴于Person类的MongoDb Collection(见下文),我想找到电子邮件地址为" not@home.com"的人。有些天真,我曾希望像tis这样的东西能起作用:

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"
                }
        ]
}

2 个答案:

答案 0 :(得分:1)

嗨现在在2.2.4中修复了 请参阅mongodb jira entry

答案 1 :(得分:0)

好吧,虽然C#驱动程序没有完全实现,但缺少很多功能,但在我看来,问题出在你的类结构中。

e.g。 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对象。