web-dev-qa-db-ja.com

CouchDBビューを値でソートする

CouchDBをテストして、検索結果のロギングをどのように処理できるかを確認しています。私がやりたいのは、結果から上位のクエリを生成できるビューを生成することです。現在、私はこのようなものを持っています:

ドキュメント部分の例

{
  "query": "+dangerous +dogs",
  "hits": "123"
}

マップ関数(私が正確に必要とするものではありませんが、テストには十分です)

function(doc) {
  if (doc.query) {
    var split = doc.query.split(" ");
    for (var i in split) {
      emit(split[i], 1);
    }
  }
}

リデュース関数

function (key, values, rereduce) {
  return sum(values);
}

これで、クエリ用語がキーで、その用語の数が右側にある形式で結果が得られます。これは素晴らしいことです。ただし、キーではなく値で並べ替えてください。そのサウンドから、これはCouchDBではまだ不可能です。

それで、私がクエリ用語の順序付けされたバージョンとそれらに関連するカウントを持っているビューをどのようにして得ることができるかについて誰かが何か考えを持っていますか?私はCouchDBを初めて使用するので、必要な関数をどのように記述するか考えられません。

38
Lee Theobald

単純な答えはありません。ただし、いくつかのパターンがあります。

  1. http://wiki.Apache.org/couchdb/View_Snippets#Retrieve_the_top_N_tags 。彼らはそれがもろい解決策であり、コードがリラックスして見えるわけではないことを認めているので、私は個人的にこれが好きではありません。

  2. Aviの答えは、アプリケーションのメモリ内で並べ替えることです。

  3. couchdb-lucene 誰もが最終的に必要とするようだと思われます!

  4. 私が好きなのは、クリスがエイヴィの引用で言ったことです。リラックス。 CouchDBでは、データベースは軽量でExcelであり、データの独自の視点を提供します。最近の話題はすべて、フィルターされたレプリケーションに関するものです。これは、データのサブセットを切り出して別のDBに配置することに関するものです。

    とにかく、基本は簡単です。あなたはあなたの.rowsビューの出力から、それを別のDBに挿入します。別のDBは、カウントされたキーを出力するだけです。追加のトリックは、非常に単純な_list 関数。生のソファー出力をさまざまな形式に「レンダリング」します。君の _list関数は出力する必要があります

    { "docs":
        [ {..view row1...},
          {..view row2...},
          {..etc...}
        ]
    }
    

    それが行うことは、_bulk_docs AP​​Iが必要です。これで、カールを別のカールに直接パイプすることができます。

    curl Host:5984/db/_design/myapp/_list/bulkdocs_formatter/query_popularity \
     | curl -X POST Host:5984/popularity_sorter/_design/myapp/_view/by_count
    
  5. 実際、リスト関数がすべてのドキュメントを処理できる場合は、それ自体を並べ替えてクライアントに返すことができます。

25
JasonSmith

これはCouchDB-userメーリングリストの 上に であり、主要な開発者の1人であるChris Andersonは次のように書いています。

これは一般的なリクエストですが、CouchDBのビューでは直接サポートされていません。これを行うには、グループ縮小クエリを別のデータベースにコピーし、値で並べ替えるビューを作成する必要があります。

これは、ダイナミックレンジクエリとインクリメンタルインデックスを優先するトレードオフです。

私も最近これを行う必要があり、アプリ層でそれを行うことになりました。これはJavaScriptで簡単に実行できます。

db.view('mydesigndoc', 'myview', {'group':true}, function(err, data) {

    if (err) throw new Error(JSON.stringify(err));

    data.rows.sort(function(a, b) {
        return a.value - b.value;
    });

    data.rows.reverse(); // optional, depending on your needs

    // do something with the data…
});

この例は Node.js で実行され、 node-couchdb を使用しますが、ブラウザーまたは別のJavaScript環境で実行するように簡単に変更できます。そしてもちろん、この概念はあらゆるプログラミング言語/環境に移植可能です。

HTH!

13
Avi Flax

これは古い質問ですが、それでもまともな回答に値するものだと思います(正解を探すために少なくとも20分は費やしました...)

ここでの回答にある他の提案には不賛成であり、不十分だと感じています。特に、アプリケーションレイヤーの行を並べ替えるという提案は、適切にスケーリングされず、DBの結果セットを制限する必要がある場合に対応できないため、私は好きではありません。

私が出会ったより良いアプローチは this thread で提案されており、クエリ内の値を並べ替える必要がある場合は、それらをキーセットに追加してから、範囲を使用してキーをクエリする必要があります-目的のキーを指定し、値の範囲を緩和します。たとえば、キーが国、州、都市で構成されている場合:

emit([doc.address.country,doc.address.state, doc.address.city], doc);

次に国のみをクエリして、残りの主要コンポーネントを無料で並べ替えます。

startkey=["US"]&endkey=["US",{}] 

順序を逆にする必要がある場合-単純な定義descending: trueでは不十分です。実際には、開始キーと終了キーの順序を逆にする必要があります。つまり、

startkey=["US",{}]&endkey=["US"]

このすばらしい source で詳細を参照してください。

4
roy650

返された結果として1があるかどうかはわかりませんが、これでうまくいくはずです。

emit([doc.hits, split[i]], 1);

ソートのルール はドキュメントで定義されています。

2

Aviの答えに基づいて、私はこのCouchdbリスト関数を思い付きました。これは、私のニーズに合った機能です。これは、最も人気のあるイベント(キー=イベント名、値=出席者)のレポートです。

 ddoc.lists.eventPopularity = function(req、res){
 start({headers:{"Content-type": "text/plain"}}); 
 var data = [] 
 while(row = getRow()){
 data.Push(row); 
} 
 data.sort(function(a、b ){
 return a.value-b.value; 
})。reverse(); 
 for(i in data){
 send(data [i ] .value + ':' + data [i] .key + "\ n"); 
} 
} 

参考までに、対応するビュー関数を次に示します。

 ddoc.views.eventPopularity = {
 map:function(doc){
 if(doc.type == 'user'){
 for(i in doc.events){
 emit(doc.events [i] .event_name、1); 
} 
} 
}、
 reduce: '_カウント'
}

そして、リスト関数の出力(抜粋):

 165:デザイン主導のイノベーション:デザイナーがダイアログを容易にする方法
 165:顧客は群衆またはコミュニティですか?
 164:ソーシャルメディアの神話家
 163:創造性を恐れないでください!起こり得ること
 159:エージェンシーはソフトウェア会社のように考える必要がありますか? .____。] 155:なぜすべてが素晴らしいのに、誰もが幸せではないのか
2
user599515

Link Retrieve_the_top_N_tagsが壊れているようですが、別の解決策 here を見つけました。

その解決策を書いた開発者を引用する:

マップステップでタグによってキー設定された結果を返すのではなく、代わりにすべてのタグの発生をすべて放出します。次に、reduceステップで、ハッシュを使用してタグでグループ化された集計値を計算し、それを配列に変換してソートし、上位3を選択します。

コメントに記載されているように、唯一の問題はロングテールの場合です。

問題は、取得するタグの数に注意する必要があることです。結果が500バイトより大きい場合、「reduceは効果的に削減する必要がある」ので、couchdbはそれについて不平を言うでしょう。 3、6、または20のタグでも問題ありません。

私にとっては完全に機能しました。リンクをチェックしてコードを確認してください!

0
edelans

上記のすべてのソリューションは、couchdbのパフォーマンスを低下させると思います。私はこのデータベースに非常に慣れていません。私が知っているように、couchdbビューはクエリされる前に結果を準備します。手動で結果を準備する必要があるようです。たとえば、各検索用語はヒットカウントとともにデータベースに存在します。そして、誰かが検索すると、その検索語が検索され、ヒット数が増加します。検索用語の人気を確認したい場合は、(ヒットカウント、検索用語)ペアが出力されます。

0
Melug