0

レッスンとトラックを保存する「要素」という名前のコレクションがあります。レッスンとトラックは、cms_content_type というフィールドを使用して区別されます。これは、レッスンの場合は「レッスン」、トラックの場合は「トラック」です。トラックであれレッスンであれ、要素を一意に識別する cms_id フィールドがあります。トラックは、track_lessons フィールドの 1 つ以上のレッスンで構成されます。

レッスン文書の構造は次のとおりです。

{
    '_id': ObjectId('1234'),
    'name': 'Working with Tags',
    'cms_content_type': 'Lesson',
    'cms_id': 'abcd1234'
}

トラック ドキュメントの構造は次のとおりです。

{
    '_id': ObjectId('4567'),
    'name': 'Tags 101',
    'cms_content_type': 'Track',
    'cms_id': 'pqrs4567'
    'track_lessons':[
        {'lesson_cms_id': 'efgh1234'},
        {'lesson_cms_id': 'jklm1234'}
    ]
}

この要素コレクションを照会して、どのトラックにも存在しないレッスンのリストを取得したいと考えています。どうすればこれを達成できますか?MapReduce は初めてです。このリストを取得するには、それを使用する必要がありますか?

もう 1 つの要件は、取得したレッスンのリストを並べ替えてページ番号を付けられることです。したがって、結果を別のコレクションに保存してそれに取り組むよりも、動的クエリを作成することをお勧めします。

どんな助けでも大歓迎です。

4

2 に答える 2

0

この要素コレクションを照会して、どのトラックにも存在しないレッスンのリストを取得したいと考えています。どうすればこれを達成できますか?

M/R は 1 つのコレクションでしか機能しないため、使用できません。スキーマの再設計はもちろん避けたいことですが、現在、ニーズに合わないものがあります。MongoDB では、正規化ルールに従ってスキーマを設計する RDBM とは異なり、データの使用方法に従ってスキーマを設計します。

したがって、これを行う最も簡単な方法cms_idは、トラックの をレッスンドキュメントとともに配列として格納することです。

{
    '_id': ObjectId('1234'),
    'name': 'Working with Tags',
    'cms_content_type': 'Lesson',
    'cms_id': 'abcd1234',
    'tracks': [ 'pqrs4567' ]
}

この方法では、面倒な M/R クエリを実行する必要がなく、次のように簡単にクエリを実行できます。

db.col.find( { tracks: { $size: 0 } );

反対方向で行ったように、ネストされた配列としてそれらを保存する必要はありませんが、代わりに ID を保存するだけです。

{
    '_id': ObjectId('4567'),
    'name': 'Tags 101',
    'cms_content_type': 'Track',
    'cms_id': 'pqrs4567'
    'track_lessons': [ 'efgh1234', 'jklm1234' ]
}

これにより、track_lessons (またはトラック) にインデックスを作成すると、より最適になります。ただし、track_lessons を完全に除外して、代わりにトラックをレッスンと共に保存することをお勧めします。

{
    '_id': ObjectId('1234'),
    'name': 'Working with Tags',
    'cms_content_type': 'Lesson',
    'cms_id': 'abcd1234',
    'tracks': [ 'pqrs4567' ]
}
{
    '_id': ObjectId('4567'),
    'name': 'Tags 101',
    'cms_content_type': 'Track',
    'cms_id': 'pqrs4567'
}

トラックに属するすべてのレッスン (たとえば、タグ 101) を保存しなくても、次のクエリを使用して、トラックに属するすべてのレッスンを簡単に照会できます。

db.col.find( { tracks: 'pqrs4567' } );

これらの変更を行うことで、M/R をまったく忘れることができるため、アプリの保守がはるかに簡単になり、高速になります。

于 2013-07-09T17:08:14.303 に答える
0

ここで M/R が役立つとは思えません。現在のデザインでは、あるコレクションの ID を別のコレクション (つまり、レッスンとトラック) で確認する必要があるためです。M/R では、map reduce 関数から db クエリを実行できません。現在の設計はデータの局所性を壊しており、外部キーの使用に関してリレーショナルに似ている傾向があります。その結果、クエリのパフォーマンス (一種の結合) で支払う必要があります。Derick のソリューションは、各ドキュメント内に必要な情報を含めることによって、この局所性の問題を克服しようとします。そして、必要なデータを 1 つのドキュメントに入れることを強くお勧めします。

現在の設計でそれを行う必要がある場合、簡単な解決策は次のとおりです。

var lessons_without_task = [];
db.lessons.find().forEach(
   function(lesson_doc) {
      var task = db.tasks.findOne({ "track_lessons.lesson_cms_id" : lesson_doc.cms_id });
      if (task == null) {
        lessons_without_task.push(lesson_doc.cms_id);
      }
   }
)

ここでは、 にマルチキー インデックスを定義したと仮定しますtrack_lessons.lesson_cms_idhttp://docs.mongodb.org/manual/core/indexes/#index-type-multi-keyを参照してください 。大規模なコレクションの場合は、次のオプションを追加する必要がある場合があります (の直後find()) 。
addOption(DBQuery.Option.awaitData).addOption(DBQuery.Option.noTimeout)

于 2013-07-09T21:56:30.533 に答える