MongoDb查询到poco项目中的单个数组项

时间:2017-01-09 22:28:31

标签: c# mongodb mongodb-.net-driver

我不确定标题是否符合我的要求,但这里是: 我有一个看起来像这样的json:

[
{
    "Class" : "Math",
    "Location" : "South Hall",
    "Professor" : "Donald Duck"
    "Student": 
    [
        {
            "FirstName" : "John",
            "LastName" : "Doh",
            "DOB" : "1990",
            "SS": "123456789"

        },
        {
            "FirstName" : "Jane",
            "LastName" : "Smith",
            "DOB" : "1990",
            "SS": "023456789"

        },
        {
            "FirstName" : "John",
            "LastName" : "Smith",
            "DOB" : "1995",
            "SS": "003456789"

        }

    ]
}

我希望能够使用学生名字和姓氏来阅读该文档,但我想只返回该学生的数组项目以及其余的json,并排除其他学生,例如,说我的疑问是:

db.Class.find({"Student.FirstName" : "Jane", "Student.LastName" : Smith"})

我希望我的回归json看起来像这样:

[
{
    "Class" : "Math",
    "Location" : "South Hall",
    "Professor" : "Donald Duck"
    "Student": 
    {
        "FirstName" : "Jane",
        "LastName" : "Smith",
        "DOB" : "1990",
        "SS": "023456789"

    }
}

任何想法如何做到这一点?我正在使用C#驱动程序,我的poco看起来像这样:

  public class Rootobject
{
    public string Class { get; set; }
    public string Location { get; set; }
    public string Professor { get; set; }
    public Student Student { get; set; }
}

public class Student
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string DOB { get; set; }
    public string SS { get; set; }
}

2 个答案:

答案 0 :(得分:1)

首先,你的POCO课程是错误的。您的根对象上没有一个学生,而是学生的共同学生。

public class Rootobject
{
    public int Id { get; set;}
    public string Class { get; set; }
    public string Location { get; set; }
    public string Professor { get; set; }
    public Student[] Student { get; set; }
}

以下是使用c#MongoDb驱动程序获取所需内容的示例代码。

从db:

加载集合
var client = new MongoClient("mongodb://localhost:27017");
var db = client.GetDatabase("testdb");

var collection = db.GetCollection<Rootobject>("students");

从mongo获取数据:

collection.Find(r => r.Student.Any(s => s.FirstName == "Jane" && s.LastName == "Smith"))
.Project(
        Builders<Rootobject>.Projection.Include(x=>x.Class)
        .Include(x=>x.Location)
        .Include(x=>x.Professor)
        .ElemMatch(x=> x.Student, y=>y.FirstName=="Jane" && y.LastName=="Smith"))   
.ToEnumerable()

此查询结果可能出现的问题是:您将获得BSonDocument,而不是rootobject。可能的解决方案是生成root对象的新实例(在ToEnumerable()之后直接使用):

.ToEnumerable()
.Select(r => new Rootobject {
            Class = r[nameof(Rootobject.Class)].AsString, 
            Location = r[nameof(Rootobject.Location)].AsString,
            Professor = r[nameof(Rootobject.Professor)].AsString,
            Student = r[nameof(Rootobject.Student)].AsBsonArray.Select(s => new Student 
                { 
                    DOB = s[nameof(Student.DOB)].AsString,
                    FirstName = s[nameof(Student.FirstName)].AsString,
                    LastName = s[nameof(Student.LastName)].AsString,
                    SS = s[nameof(Student.SS)].AsString,
                }).ToArray(),
            })

其他可能性:您将所有学生的根对象发送给客户,并在查询结果中过滤您的学生:

var result = collection
     .Find(r => r.Student
                 .Any(s => s.FirstName == "Jane" && s.LastName == "Smith")).ToEnumerable()
.Select(r =>
{
    r.Student = r.Student.Where(s => s.FirstName == "Jane" && s.LastName == "Smith")
                         .ToArray();
    return r;
})

答案 1 :(得分:0)

尝试以下aggregate

db.collection.aggregate(
[ 
    { $unwind: "$Student" },
    { $match: {"Student.FirstName" : "John", "Student.LastName" : "Doh"}}, 
    { $unwind: "$Student" },
    { $project: { "Student" : 1 , "Professor" : 1, "Class" : 1, "Location" : 1, "_id" : 0}}
]
);

输出:

{
    "Class" : "Math",
    "Location" : "South Hall",
    "Professor" : "Donald Duck",
    "Student" : {
        "FirstName" : "John",
        "LastName" : "Doh",
        "DOB" : "1990",
        "SS" : "123456789"
    }
}

希望这会有所帮助。