2016-12-16 10 views
0

私はモンゴにポートに既存のSQLスキーマをしようとしています上のフィールドの値とフィルタを備えた最新であるかどうかを取得します。
は、我々は異なるリビジョンが、同じ参照しながら、時には数回同じ文書で、文書のテーブルを持っています。私は最新のリビジョンだけを入手したいと思っています。MongoDBは:文書が結果

サンプルの入力データ:

このデータは、私は(時々私は時々私は属性を持つすべてのリビジョンは、それが最新だかどうか私に言って欲しい、唯一の最後のリビジョンを望む)この結果セットを望む考える
{ 
    "Uid" : "xxx", 
    "status" : "ACCEPTED", 
    "reference" : "DOC305", 
    "code" : "305-D", 
    "title" : "Document 305", 
    "creationdate" : ISODate("2011-11-24T15:13:28.887Z"), 
    "creator" : "X" 
}, 
{ 
    "Uid" : "xxx", 
    "status" : "COMMENTED", 
    "reference" : "DOC306", 
    "code" : "306-A", 
    "title" : "Document 306", 
    "creationdate" : ISODate("2011-11-28T07:23:18.807Z"), 
    "creator" : "X" 
}, 
{ 
    "Uid" : "xxx", 
    "status" : "COMMENTED", 
    "reference" : "DOC306", 
    "code" : "306-B", 
    "title" : "Document 306", 
    "creationdate" : ISODate("2011-11-28T07:26:49.447Z"), 
    "creator" : "X" 
}, 
{ 
    "Uid" : "xxx", 
    "status" : "ACCEPTED", 
    "reference" : "DOC501", 
    "code" : "501-A", 
    "title" : "Document 501", 
    "creationdate" : ISODate("2011-11-19T06:30:35.757Z"), 
    "creator" : "X" 
}, 
{ 
    "Uid" : "xxx", 
    "status" : "ACCEPTED", 
    "reference" : "DOC501", 
    "code" : "501-B", 
    "title" : "Document 501", 
    "creationdate" : ISODate("2011-11-19T06:40:32.957Z"), 
    "creator" : "X" 
} 

{ 
    "Uid" : "xxx", 
    "status" : "ACCEPTED", 
    "reference" : "DOC305", 
    "code" : "305-D", 
    "title" : "Document 305", 
    "creationdate" : ISODate("2011-11-24T15:13:28.887Z"), 
    "creator" : "X", 
    "lastrev" : true 
}, 
{ 
    "Uid" : "xxx", 
    "status" : "COMMENTED", 
    "reference" : "DOC306", 
    "code" : "306-B", 
    "title" : "Document 306", 
    "creationdate" : ISODate("2011-11-28T07:26:49.447Z"), 
    "creator" : "X", 
    "lastrev" : true 
}, 
{ 
    "Uid" : "xxx", 
    "status" : "ACCEPTED", 
    "reference" : "DOC501", 
    "code" : "501-B", 
    "title" : "Document 501", 
    "creationdate" : ISODate("2011-11-19T06:40:32.957Z"), 
    "creator" : "X", 
    "lastrev" : true 
} 

私はすでに、フィルタの束を持って並べ替え、および(データのページネーション用)/限度をスキップし、最終的な結果セットには、これらの制約に留意する必要があります。

細かいフィルタリングが、私は、各ドキュメントのすべてのリビジョンを与える(.NETドライバで構築された)クエリ、「見つける」現在:another questionを使用して

coll.find(
    { "$and" : [ 
     { "$or" : [ 
      { "deletedid" : { "$exists" : false } }, 
      { "deletedid" : null } 
     ] }, 
     { "$or" : [ 
      { "taskid" : { "$exists" : false } }, 
      { "taskid" : null } 
     ] }, 
     { "objecttypeuid" : { "$in" : ["xxxxx"] } } 
    ] }, 
    { "_id" : 0, "Uid" : 1, "lastrev" : 1, "title" : 1, "code" : 1, "creator" : 1, "owner" : 1, "modificator" : 1, "status" : 1, "reference": 1, "creationdate": 1 } 
).sort({ "creationdate" : 1 }).skip(0).limit(10); 

を、私はこの凝集を構築することができました、これは私に、各文書の最新版を与えるが、その結果では十分ではない属性を持つ:

coll.aggregate([ 
    { $sort: { "creationdate": 1 } }, 
    { 
     $group: { 
      "_id": "$reference", 
      result: { $last: "$creationdate" }, 
      creationdate: { $last: "$creationdate" } 
     } 
    } 
]); 

私は、検索クエリで集計を統合したいと思います。 、それぞれの結果ノードの場合

coll.aggregate(
[ 
    { $match: { 
      "$and" : [ 
       { "$or" : [ 
        { "deletedid" : { "$exists" : false } }, 
        { "deletedid" : null } 
       ] }, 
       { "$or" : [ 
        { "taskid" : { "$exists" : false } }, 
        { "taskid" : null } 
       ] }, 
       { "objecttypeuid" : { "$in" : ["xxx"] } } 
      ] 
     } 
    }, 
    { $sort: { "creationdate": 1 } }, 
    { $group: { 
      "_id": "$reference", 
      "doc": { "$last": "$$ROOT" } 
     } 
    }, 
    { $sort: { "doc.creationdate": 1 } }, 
    { $skip: skip }, 
    { $limit: limit } 
], 
    { allowDiskUse: true } 
); 

これは私の文書データと「ドキュメント」ノードを与える:

+0

あなたは '内のデータのグループを提供しますJSON形式? – Shawyeok

+0

はい!サンプルデータ、期待されるサンプル結果、既存のクエリを追加しました。 – thomasb

+0

あなたは、処理したいフィールドを '$ first' /' $ last'を使ってグループステージに追加する必要があります。 – Veeram

答えて

0

私は、集約およびフィルタリングを混合する方法を発見しました。あまりにも多くのデータが残っています(投影が欠落しています)。しかし、それはスタートです。

は.NETの翻訳:

FilterDefinitionBuilder<BsonDocument> filterBuilder = Builders<BsonDocument>.Filter; 
FilterDefinition<BsonDocument> filters = filterBuilder.Empty; 

filters = filters & (filterBuilder.Not(filterBuilder.Exists("deletedid")) | filterBuilder.Eq("deletedid", BsonNull.Value)); 
filters = filters & (filterBuilder.Not(filterBuilder.Exists("taskid")) | filterBuilder.Eq("taskid", BsonNull.Value)); 
foreach (var f in fieldFilters) { 
    filters = filters & filterBuilder.In(f.Key, f.Value); 
} 

var sort = Builders<BsonDocument>.Sort.Ascending(orderby); 

var group = new BsonDocument { 
    { "_id", "$reference" }, 
    { "doc", new BsonDocument("$last", "$$ROOT") } 
}; 

var aggregate = coll.Aggregate(new AggregateOptions { AllowDiskUse = true }) 
    .Match(filters) 
    .Sort(sort) 
    .Group(group) 
    .Sort(sort) 
    .Skip(skip) 
    .Limit(rows); 

return aggregate.ToList(); 

私も、これを行うには良い方法があるかなり確信しています。

0

あなたの答えはかなり近いです。 $lastの代わりに$maxが良いです。

について$最後のオペレータ:

フィールドで同じグループを共有する文書のグループ内の最後の文書に式を適用した結果の値を返します。文書が定義された順序である場合にのみ意味があります。

mongo shellで以下のコードを参照、各グループに最後のリビジョンを取得:あなたの期待通り

db.collection.aggregate([ 
    { 
    $group: { 
     _id: '$reference', 
     doc: { 
     $max: { 
      "creationdate" : "$creationdate", 
      "code" : "$code", 
      "Uid" : "$Uid", 
      "status" : "$status", 
      "title" : "$title", 
      "creator" : "$creator" 
     } 
     } 
    } 
    }, 
    { 
    $project: { 
     _id: 0, 
     Uid: "$doc.Uid", 
     status: "$doc.status", 
     reference: "$_id", 
     code: "$doc.code", 
     title: "$doc.title", 
     creationdate: "$doc.creationdate", 
     creator: "$doc.creator" 
    } 
    } 
]).pretty() 

出力を:

{ 
    "Uid" : "xxx", 
    "status" : "ACCEPTED", 
    "reference" : "DOC501", 
    "code" : "501-B", 
    "title" : "Document 501", 
    "creationdate" : ISODate("2011-11-19T06:40:32.957Z"), 
    "creator" : "X" 
} 
{ 
    "Uid" : "xxx", 
    "status" : "COMMENTED", 
    "reference" : "DOC306", 
    "code" : "306-B", 
    "title" : "Document 306", 
    "creationdate" : ISODate("2011-11-28T07:26:49.447Z"), 
    "creator" : "X" 
} 
{ 
    "Uid" : "xxx", 
    "status" : "ACCEPTED", 
    "reference" : "DOC305", 
    "code" : "305-D", 
    "title" : "Document 305", 
    "creationdate" : ISODate("2011-11-24T15:13:28.887Z"), 
    "creator" : "X" 
} 
+0

あなたの例では、maxは 'creationdate'フィールドの最大値を取得しなければならないと判断しますが、他の値は取得しません。 – thomasb

+0

'creationdate'は' $ max'引数オブジェクトの最初のフィールドなので、 '$ max'演算子は定義された順序でフィールドごとに1つずつソートします。しかしそれは文書化されていないので、ソースコードで確認する必要があります。 – Shawyeok

+0

ok、ありがたいですが、私は文書化されていない機能に頼るのが大好きではありません... – thomasb

関連する問題