2

ここには、CouchDBを使用したページ付けに関連する質問がたくさんありますが、私が疑問に思っていることに完全に一致するものはありません。

基本的に、投票数でランク付けされた結果セットがあり、セットを降順でページングしたいと思います。

map参考までにこちらをご覧ください。

function(doc) {
  emit(doc.votes);
}

さて、問題。startkey_docidそれだけではうまくいかないことがわかりました。と組み合わせて使用​​する必要がありますstartkey。重要なのは、クエリではstartkeyパラメーターを使用しないことです(結果を制限するつもりはなく、最大->最小を取得するだけです)。代わりにstartkey={{doc.votes}}&startkey_docid = {{doc._id}}を使用できると思っていましたが、誰かが[次のページ]リンクをクリックするまでに、ドキュメントの投票数が変わった可能性があります。

これを解決する方法は明らかなようでした。startkey=99999999データベース内のすべてのドキュメントが返されるように設定するだけstartkey_docidで、前回中断したドキュメントから開始できます。奇妙なことに、私がそれを行うと、startkey_docid動作が停止し、すべての結果が再び返されるようになりました。どうやらで使用されstartkeyているドキュメントのキーと正確に等しい必要があります。_idstartkey_docid

私が質問しているのは、実際に使用したい時間までにstartkey_docid実際のページが変更された可能性があるときに、ページに使用するための回避策を誰かが知っているかどうかです。startkey私のアプリケーションは、ドキュメントを検索し、リクエスト間の数ミリ秒で変更されていないことを期待して_id、すぐに値を使用する必要がありますか?doc.votesそれでもあまり信頼できないようです。

編集:速度のためにMongoに切り替えることになったので、この質問はちょっと議論の余地があることがわかりました。

4

3 に答える 3

1

私はこのようなことをしたことがありませんが、それを行う方法についてはある程度のアイデアがあると思います。あなたができることは、評価のスナップショットを取り、それをすべてのページで参照することです. ビューが多くのスペースを消費しないようにするため、スナップショットの取得後に投票が変更されていないドキュメントの個別のコピーをマップしないでください。したがって、次のことができます。

  1. タイムスタンプ付きの評価の履歴をドキュメントに追加します。
  2. このように評価と履歴をマッピングします。
  3. アプリで現在の時刻を取得し、start_time = Date.now()すべてのページを照会します。
  4. 最も古いアクティブなセッションよりも古い履歴をクリーンアップします。

問題は、[votes, date]発行してページ分割しようとすると、ページごとに必要な数を取得するためにフェッチする必要があるドキュメントの数がわからないことです。スキップしなければならない古いバージョンが常に存在する可能性があり、次に DB から取得する必要があります。これが、発行を検討できる理由です: [date, votes]、ビューを常に2回読み取ります-start_time現在の時間、および結果をマージしてソートします(マージソートのように)。

Ad.1:

{ ...,
  votes: 12,
  history: [
    {date: 1357390271342, votes: 10},
    {date: 1357390294682, votes: 11}
  ]
}

Ad.2:

function (doc) {
  emit([{}, doc.votes], null);
  doc.history && doc.history.forEach(function(h) {
    emit([h.date, h.votes], null);
  });
}

Ad.3:

?startkey=[start_time, votes]&limit=items_per_page_plus1
?startkey=[{}, votes]&limit=items_per_page_plus1

リストをマージvotesし、アプリで並べ替えます (リスト機能で)。使用に問題がある場合は、ID を明示的に発行してクエリを実行start_docidできます。[date, votes, id]この特定のドキュメントが変更votesされた場合でも、履歴で引き続き使用できます。

Ad.4: 出力する[date, votes]と、古い履歴 width:?startkey=[0]&endkey=[oldest_active_session_time]&inclusive_end=falseを取得し、update handlerで更新できます:

function(doc, req) {
  if (!doc || !doc.history) return [null, 'Error'];
  var history = new Array();
  var oldest = +(req.query.date);
  doc.history.forEach(function(h) {
    if (h.date >= oldest)
      history.push(h);
  });
  doc.history = history;
  return [doc, 'OK'];
}

注:私はそれをテストしていないので、変更なしでは実行できないと予想されます:)

私が知る限り、CouchDB は b-tree シャドーイングを使用して更新を行っており、原則としてビューの古いリビジョンにアクセスできるはずです。私は CouchDB の設計には興味がないので、これは単なる推測であり、このための (文書化された) API はないようです。

于 2013-01-05T13:53:09.053 に答える
0

今のところ簡単な解決策はわかりませんが、オプションがあります。

  • それほど頻繁ではないソートリストを小さな専用データベースに複製して、stale=ok よりもはるかに古くなるようにします
  • より安定したデータでソートできるようにスキーマを変更します。CouchDb ガイドの銀行/台帳の例を見てください: http://guide.couchdb.org/draft/recipes.html#banking。たとえば、すべての投票を記録し、1 時間ごとに減らすようにしてください。ボーナスとして、履歴/トレンドを取得できます:)
于 2013-01-05T14:05:14.740 に答える