2017-01-09 11 views
0

私は私が探しています何のタイトルマッチであればわからないが、ここでは、次のとおりです。 私はこのようになりますJSONを持っている:MongoDBのクエリの単一のアレイ項目

[ 
{ 
    "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; } 
} 

答えて

0

まず、あなたのPOCOクラスは間違っています。ルートオブジェクトには1人の学生しかいるわけではなく、学生の集まりです。

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ドライバで必要なものを得るためのサンプルコードを示します。モンゴからデータを取得するには

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

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

::DBからコレクションをロードするために

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を取得します。

.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(), 
      }) 

その他の可能性:あなたは、クライアントにすべての学生とあなたのルートオブジェクトを取得し、クエリの結果に、既にあなたの学生をフィルタリング可能な解決策は、あなたのrootobjectsの新しいインスタンスを(ToEnumerable()直後に使用)を生成することです:

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; 
}) 
+0

@Pacman答えがあなたを助けたなら、私はアップフォートに感謝します。 –

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

・ホープ、このことができます。

関連する問題