0

RethinkDB (2.3.5~0trusty) と python (2.7.6) と python-rethinkdb バインディング (2.3.0.post6) を使用して、既存のデータベースにクエリを実行しようとしています。(つまり、使用しているスキーマを変更できないと仮定してください)

これは私が抱えている問題の簡単な例です。

テーブルなどの名前は、人々がより慣れているドメインに移動されましたが、私が抱えている問題は構造的に同等です (そしてよりコンパクトです)。

借り手

Schema: (borrower_id:key (primary), name :string, favourite_authors : list of author_id )

Sample data:
{ "borrower_id": "91a15585-f084-41b3-9df1-1a3b16a8daed",
  "name": "Jo",
  "favourite_authors" : [ "b9503702-8832-43c8-a3f0-34691635419a",
                          "3bae9a66-2de6-4c64-ae95-c5f7caad86bb",
                        ]
}
{ "borrower_id": "23a8a193-c32e-4332-a40b-2ba56d158205",
  "name": "Bob",
  "favourite_authors" : [ "41305d3b-2819-4af5-be62-3c7999c4d747",
                          "d270f08d-aab1-4644-8dea-8f4fdd2d80b4"
                        ]
}
{ "borrower_id": "01031fb0-35de-4324-af47-611fec9ca7ad",
  "name": "Sam",
  "favourite_authors" : [ "b9503702-8832-43c8-a3f0-34691635419a"
                        ]
}

著者

Schema: (author_id:key (primary), name :string, books_written : list of book_id )

Sample data:
{ "author_id": "b9503702-8832-43c8-a3f0-34691635419a",
  "name": "Joanna Smith",
  "books_written" : [ "c1a48e2e-a831-4f5b-95b2-9b429dcf34e5",
                      "8f0e89b6-78e8-45ec-b7db-9cf3e00e0a8d",
                    ]
}
{ "author_id": "3bae9a66-2de6-4c64-ae95-c5f7caad86bb",
  "name": "John Smith",
  "books_written" : [ "8f0e89b6-78e8-45ec-b7db-9cf3e00e0a8d",
                      "b9fb4de0-e3bd-4df1-b192-c9a0ae7fb2e1",
                    ]
}
{ "author_id": "41305d3b-2819-4af5-be62-3c7999c4d747",
  "name": "Jo Smith",
  "books_written" : [ "b9fb4de0-e3bd-4df1-b192-c9a0ae7fb2e1",
                      "37b6eb03-e8ea-43dc-b3e4-ffc0bbfb1154",
                    ]
}
{ "author_id": "d270f08d-aab1-4644-8dea-8f4fdd2d80b4",
  "name": "Jim Smith",
  "books_written" : [ "8f0e89b6-78e8-45ec-b7db-9cf3e00e0a8d",
                      "37b6eb03-e8ea-43dc-b3e4-ffc0bbfb1154",
                    ]
}

書籍

Schema: (book_id:key (primary), name:string, book_info: object, may contain a data
                                                        dict, that has a list of
                                                        repeatable metadata options...)

Sample data:
{ "book_id": "c1a48e2e-a831-4f5b-95b2-9b429dcf34e5",
  "name": "",
  "book_info" : {
      "data" : [
                { "tag": "sf },
                { "period" : "past"}
               ]
        }
}
{ "book_id": "8f0e89b6-78e8-45ec-b7db-9cf3e00e0a8d",
  "name": "",
  "book_info" : {
      "data" : [
                { "tag": "romance },
                { "period" : "present"}
               ]
        }
}
{ "book_id": "89b68f0e-78e8-45ec-b7db-9cf3e00e0a8d",
  "name": "",
  "book_info" : {
      "data" : [
                { "period" : "present"}
               ]
        }
}
{ "book_id": "b9fb4de0-e3bd-4df1-b192-c9a0ae7fb2e1",
  "name": "",
  "book_info" : {
      "data" : [
                { "tag": "sf },
                { "tag": "romance},
                { "period" : "present"}
               ]
        }
}
...
{ "book_id": "37b6eb03-e8ea-43dc-b3e4-ffc0bbfb1154",
  "name": "",
  "book_info" : {
      "data" : [
                { "tag": "sf },
                { "period" : "future"}
               ]
        }
}

さて、私が実行したい一般的なクエリはこれと同等です:

  • 「「SF」の本を書いた著者を好きな借り手のリストを教えてください...

注: 書籍情報のデータ セクションにすべての書籍のタグ オプションがあるわけではありません...

RethinkDB の ReQL クエリ インターフェイスを使用して、結合とフィルターの組み合わせを見つけようとしていますが、これを実行できると確信していますが、明確な方法がわかりません。

私の出発点は、RethinkDB のさまざまな結合オプションを調べることでしたが、原子キーだけでなく、外部キーのリストを含む属性を使用して結合を実行する明白な方法がわかりません。(私は通常、繰り返されるフィールドに外部キーを置くか、関係テーブルを持っていますが、私が言うように、私が持っている構造を変更することはできません)

私はPython指向のソリューションを好みますが、変換できるので、javascript(または他の言語)が便利です:-)

どんな提案でも大歓迎です。

4

1 に答える 1

1

このコード (Javascript) は次のことを行います。

r.db("test").table("Borrowers").filter(function(borrower){ 
  return borrower("favourite_authors").setIntersection(r.db("test").table("Authors").filter(function(author){ 
    return author("books_written").setIntersection(r.db("test").table("Books").filter(function(book){ 
      return book("book_info")("data").contains({"tag": "sf"}); })("book_id").coerceTo("array")).isEmpty().not();})("author_id").coerceTo("array")).isEmpty().not();}) 

しかし、サンプルデータだけを含むデータベースでは、すでに非常に遅いです(私のサーバーでは35〜70ミリ秒)

これは基本的に 3 つのサブクエリの組み合わせです。

1:

r.db("test").table("Books").filter(function(book){ 
  return book("book_info")("data").contains({"tag": "sf"}); })("book_id").coerceTo("array")

これは最も内側のものです。sf としてタグ付けされたすべての書籍の ID を含む配列を取得します。この配列は、次のサブクエリに入れられます。

r.db("test").table("Authors").filter(function(author){ 
  return author("books_written").setIntersection(<book ids go here>).isEmpty().not();})("author_id").coerceTo("array")

これは、指定された 1 つ以上の本に参加したすべての著者 ID の配列を取得します。著者の本と sf 本の配列の交差部分が空でないことによってフィルタリングします。(交差点が空でない場合、著者の少なくとも 1 冊の本が sf としてタグ付けされます)

r.db("test").table("Borrowers").filter(function(borrower){ 
  return borrower("favourite_authors").setIntersection().isEmpty().not();})

最後の部分は、2 番目の部分と同じ原則に基づいており、最後に、SF の本を書いた著者を支持する借り手を返します。

于 2016-12-17T00:37:10.373 に答える