Этот вопрос был полностью переписан 10/17/18
Для того, чтобы иметь «Редактирование системы управления версиями» (аналогично StackOverflow по функциональности) Я настроил следующие классы:
tags = db.Table(
"tags",
db.Column("tag_id", db.Integer, db.ForeignKey("tag.id")),
db.Column("post_version_id", db.Integer,
db.ForeignKey("post_version.id"))
)
class Tag(db.Model):
id = db.Column(db.Integer, primary_key=True)
tag = db.Column(db.String(128), index=True, unique=True)
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
head_id = db.Column(db.Integer, db.ForeignKey("post_version.id"))
class PostVersion(db.Model):
id = db.Column(db.Integer, primary_key=True)
previous_id = db.Column(db.Integer, db.ForeignKey("post_version.id"), default=None)
pointer_id = db.Column(db.Integer, db.ForeignKey("annotation.id"))
current = db.Column(db.Boolean, index=True)
tags = db.relationship("Tag", secondary=tags)
Исключены не относящиеся к делу столбцы, такие как содержимое сообщения и т. Д. Фактически, настоящая модель данных - это аннотации; Я упростил эти модели для универсальности
Фактические данные состоят из 136 Post
, размеченных и изменяемых версиями посредством правок;то есть я произвел 136 Post
х.У меня 15 Tag
х.Начальные 136 Post
были помечены последовательно с 2 Tag
.Впоследствии я помечал Post
различными тегами (используя мою систему редактирования; таким образом, для отредактированных Post
было несколько PostVersion
).
Как вы, вероятно, заметите,есть круговая ссылка между Post и PostVersion;Я использую это для настройки следующих двух отношений для экспериментов:
Отношение 1 posts
posts = db.relationship("Post",
secondary="join(tags, PostVersion,"
"tags.c.post_version_id==PostVersion.id)",
primaryjoin="Tag.id==tags.c.tag_id",
secondaryjoin="Post.head_id==PostVersion.id",
lazy="dynamic")
, основанное на операторе SQL
SELECT
post.id
FROM
tag
JOIN
tags ON tag.id=tags.tag_id
JOIN
post_version ON tags.post_version_id=post_version.id
JOIN
post ON post.head_id=post_version.id
WHERE
tag.id=<tag_id>
и
Отношение 2 posts2
posts2 = db.relationship("Post",
secondary="join(tags, PostVersion,"
"and_(tags.c.post_version_id==PostVersion.id,"
"AnnotationVersion.current==True))",
primaryjoin="Tag.id==tags.c.tag_id",
secondaryjoin="PostVersion.pointer_id==Post.id",
lazy="dynamic")
на основе оператора SQL
SELECT
annotation.id
FROM
tag
JOIN
tags ON tag.id=tags.tag_id
JOIN
annotation_version ON tags.annotation_version_id=annotation_version.id AND
annotation_version.current=1
JOIN
annotation ON annotation_version.pointer_id = annotation.id
WHERE
tag_id=8;
Это дает следующие данные:
Tag Actual len(t.posts.all()) len(t.posts.paginate(1,5,False).items)
t1 0 0 0
t2 1 136 5
t3 1 136 5
t8 136 136 1
t14 136 136 1
t15 24 136 1
Tag Actual t.posts.count() t.posts2.count()
t1 0 0 0
t2 1 136 163
t3 1 136 163
t8 136 22168 26569
t14 136 22168 26569
t15 24 3264 3912
Iисключили избыточные теги (т. е. все остальные Tag
с 0 Post
) и идентичные данные (т. е. результаты posts2
, которые были такими же, как для posts
).
Как видите, есть серьезные проблемы с результатами!Особенно, когда для обоих отношений , если lazy="dynamic"
выключен, правильные Post
всегда возвращаются .
Используя echo=True
при создании движка, @ IljaEverilä обнаружилчто lazy="dynamic"
меняет SQL.Я цитирую комментарии в этом вопросе:
В двух словах: с lazy="dynamic"
вы получаете FROM post, tags, post_version WHERE ...
, но без вас FROM post, tags JOIN post_version ON tags.post_version_id = post_version.id WHERE ....
Как вы можете видеть, ваш составной вторичный объект в значительной степени игнорируетсяс динамической настройкой.Теперь вопрос «почему?»
Мой вопрос:
1.Это ошибка?
2.Что я могу сделать, чтобы исправить это затруднительное положение?
Обновление:
Кажется, lazy="dynamic"
явно не рекомендуется здесь , но альтернативы не предлагается.Какая альтернатива по-прежнему позволяет разбивать на страницы и рассчитывать на большие коллекции?По умолчанию это не допускается (или, по крайней мере, в том виде, в котором я к нему обращаюсь), и документация, похоже, не проясняет проблему!В разделе под названием Какой тип загрузки использовать? Стратегия загрузки, которую он рекомендует использовать для больших коллекций, составляет lazy="subquery"
, но это не допускает paginate()
и count()
.
.