2013-11-15 2 views
5

公式のpythonドライバでRethinkdb 1.10.1を使用しています。私は1人のユーザーに関連付けられているタグ付けされたもののテーブルを持っている:rethinkdbで複合マルチインデックスを作成するにはどうすればよいですか?

{ 
    "id": "PK", 
    "user_id": "USER_PK", 
    "tags": ["list", "of", "strings"], 
    // Other fields... 
} 

私はuser_idtag(例えば、タグ「タグ」を持つユーザー「tawmas」ですべてのものを見つけるために)で照会します。 、

res = (r.table('things') 
     .get_all('TAG', index='tags') 
     .filter(r.row['user_id'] == 'USER_PK').run(conn)) 

しかし、このクエリはまだ与えられたタグを持つすべての文書をスキャンする必要があります。

r.table('things').index_create('tags', multi=True).run(conn) 

私のクエリは次のようになります。Rethinkdb 1.10以降では、私は、このようなマルチインデックスを作成することができますそこで私はuser_idとtagsフィールドに基づいて複合インデックスを作成したいと思います。このようなインデックスを使用すると、次のクエリを使用できます。

res = r.table('things').get_all(['USER_PK', 'TAG'], index='user_tags').run(conn) 

複合マルチインデックスについては、ドキュメントには何もありません。しかし、 は、["USER_PK", "tag"]ペアのリストを返すことによって、複合インデックスのインデックスとマルチインデックスの要件を組み合わせたカスタムインデックス関数を使用しようとしました。

私の最初の試みは、pythonでいた:

r.table('things').index_create(
    'user_tags', 
    lambda each: [[each['user_id'], tag] for tag in each['tags']], 
    multi=True).run(conn) 

はこれが(私はリストの内包表記は本当にドライバーによってサポートされていないと思います)、インデックス機能を解析しようMemoryErrorとPythonのドライバチョークを作ります。

だから、私は私の(確かに、さび)になって、JavaScriptとこれを思い付いた:

r.table('things').index_create(
    'user_tags', 
    r.js(
     """(function (each) { 
      var result = []; 
      var user_id = each["user_id"]; 
      var tags = each["tags"]; 
      for (var i = 0; i < tags.length; i++) { 
       result.push([user_id, tags[i]]); 
      } 
      return result; 
     }) 
     """), 
    multi=True).run(conn) 

これは、好奇心旺盛な例外を除いて、サーバーによって拒否されていますrethinkdb.errors.RqlRuntimeError: Could not prove function deterministic. Index functions must be deterministic.

だから、何です複雑なマルチインデックスを定義する正しい方法は?それとも今のところサポートされていない何か ですか?

+0

ところで。 Rethink pythonドライバの最新バージョンでは、これを実行すると、私が間違っていることを説明するエラーメッセージが表示されます。古いバージョンのドライバがインストールされている可能性はありますか? –

+0

私は先週インストールされたバージョン1.10.0-0を持っています。 PyPIで公開されている新しいバージョンはないようです。あなたは開発版を指していますか? – tawmas

答えて

7

短い回答:

リストの補完はReQL関数では機能しません。これは、実際にRethinkDBドライバがどのように動作するかの、やや微妙な側面です

r.table('things').index_create(
    'user_tags', 
    lambda each: each["tags"].map(lambda tag: [each['user_id'], tag]), 
    multi=True).run(conn) 

長い答え

:あなたは代わりにそのようmapを使用する必要があります。だから、これがうまくいかない理由は、あなたのpythonコードが実際に各文書の実際のコピーを見ないということです。だから、式の中で:

lambda each: [[each['user_id'], tag] for tag in each['tags']] 

each今までに、データベースから実際の文書にバインドされていない、それが文書を表し、特別なPythonの変数にバインドされています。私は実際にそれを証明するために、次の実行してみたい:

q = r.table('things').index_create(
     'user_tags', 
     lambda each: print(each)) #only works in python 3 

をそして、それはのようなものプリントアウトします:ドライバはこれだけには、特に、関数から変数であることを知っている

<RqlQuery instance: var_1 > 

each["tags"]が配列かどうか(それは実際には非常に似た抽象オブジェクトです)は分かりません。だから、pythonはそのフィールドを反復する方法を知らない。基本的に全く同じ問題がjavascriptに存在します。

+1

ありがとう!私は完全にドキュメントのマップ機能を見落としました。 – tawmas

関連する問題