5

公式のpythonドライバーでRethinkdb 1.10.1を使用しています。1人のユーザーに関連付けられているタグ付けされたもののテーブルがあります:

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

user_idandでクエリを実行したいtag(たとえば、ユーザー "tawmas" でタグ "tag" を持つすべてのものを検索する)。Rethinkdb 1.10 から、次のようなマルチインデックスを作成できます。

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

私のクエリは次のようになります。

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

ただし、このクエリでも、指定されたタグを持つすべてのドキュメントをスキャンする必要があるため、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.

では、複合マルチインデックスを定義する正しい方法は何ですか? それとも、現時点ではサポートされていないものですか?

4

1 に答える 1

7

簡潔な答え:

リスト内包表記は ReQL 関数では機能しません。map代わりに次のように使用する必要があります。

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

長い答え

これは実際には、RethinkDB ドライバーがどのように機能するかのやや微妙な側面です。したがって、これが機能しない理由は、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に存在します。

于 2013-11-15T18:04:36.527 に答える