工具:Peewee 3,SQLite,Python 3
Peewee 3递归公用表表达式(cte)的官方文档:http://docs.peewee-orm.com/en/latest/peewee/querying.html#common-table-expressions
我将家谱存储在称为Person
的简单自引用表中。结构(如下所示):id
,name
,parent
,custom_order
注意:-如果此人是祖先/根项目,则parent
字段等于null
,否则,如果此人是孩子,则等于父记录的id
-custom_order
是浮点数(分数是确定用户最喜欢的人的分数)
目标:我想检索整个家谱,然后按parent
首先对结果进行排序,然后按custom_order
进行第二次排序。
问题:我设法获得了结果列表,但订单错误。
数据库模型
class Person(Model):
name = CharField()
parent = ForeignKeyField('self', backref='children', null = True)
custom_order = FloatField()
注意:如果parent
字段为空,则为根项目
查询代码
# Define the base case of our recursive CTE. This will be people that have a null parent foreign-key.
Base = Person.alias()
base_case = (Base
.select(Base)
.where(Base.parent.is_null())
.cte('base', recursive=True))
# Define the recursive terms.
RTerm = Person.alias()
recursive = (RTerm
.select(RTerm)
.join(base_case, on=(RTerm.parent == base_case.c.id)))
# The recursive CTE is created by taking the base case and UNION ALL with the recursive term.
cte = base_case.union_all(recursive)
# We will now query from the CTE to get the people
query = cte.select_from(cte.c.id, cte.c.name, cte.c.parent_id, cte.c.custom_order).order_by(cte.c.parent_id, cte.c.custom_order)
print(query.sql())
打印查询语法
('WITH RECURSIVE "base" AS
(
SELECT "t1"."id", "t1"."name", "t1"."parent_id", "t1"."custom_order" FROM "person" AS "t1" WHERE ("t1"."parent_id" IS ?)
UNION ALL
SELECT "t2"."id", "t2"."name", "t2"."parent_id", "t2"."custom_order" FROM "person" AS "t2" INNER JOIN "base" ON ("t2"."parent_id" = "base"."id")
)
SELECT "base"."id", "base"."name", "base"."parent_id" FROM "base"
ORDER BY "base"."parent_id", "base"."custom_order"',
[None])
问题根源问题中发布的代码可以正常工作。我通过将查询结果打印到控制台来验证它:
query = cte.select_from(cte.c.id, cte.c.name, cte.c.parent_id, cte.c.custom_order).order_by(cte.c.parent_id, cte.c.custom_order).dicts()
print(json.dumps(list(query), indent=4))
问题源于以下事实:我在将查询结果打印到控制台之前将查询结果传递给嵌套的python Dictionary
,但Python Dictionary
为无序。因此,难怪打印结果的顺序与数据库结果的顺序不同。
解决方案如果要以固定顺序存储查询结果,请使用Python Ordered Dictionary
:
import collections
treeDictionary = collections.OrderedDict()