我使用RethinkDB(2.3.5~0trusty)和python(2.7.6)以及python-rethinkdb 绑定(2.3.0.post6),并尝试查询预先存在的数据库。 (即请假设我无法更改我正在使用的架构)
这是我遇到的问题的简化示例。
表/ etc的名称已被移动到人们更常用的域中 但是,我遇到的问题在结构上是相同的(并且更紧凑)。
借款人
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"}
]
}
}
现在,我要执行的常见查询等同于:
注意:并非所有图书都在图书信息的数据部分中都有标签选项...
我试图找出使用连接和过滤器的组合 RethinkDB的ReQL查询界面 - 我保证可以做到这一点 - 但我无法看到明显的方法。
我的出发点是查看RethinkDB的各种连接选项, 但我看不到使用属性执行连接的任何明显方法 它包含外键列表而不仅仅是原子键。 (我通常会把外键放在得到的字段上 重复或有关系表,但正如我所说,我无法改变 结构我有)
我更喜欢面向python的解决方案,但javascript(或任何其他语言)会很方便,因为我可以转换: - )
欢迎任何建议。
答案 0 :(得分: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-70ms)上已经非常慢了
它基本上是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")
它检索参与一个或多个给定书籍的所有作者ID的数组。它通过作者书籍和科幻小说书籍的交集而非空虚过滤。 (如果交集非空,则至少有一本作者的书被标记为sf)
r.db("test").table("Borrowers").filter(function(borrower){
return borrower("favourite_authors").setIntersection().isEmpty().not();})
最后一部分基于与第二部分相同的原则,最后归还了那些赞成撰写科幻小说的作者的借款人。