2

スレッドが個別のテーブルではなく、投稿の複合主キーを持つフラットなフォーラムを作成したいと考えています。

そのため、投稿には自然キーを形成する 2 つのフィールドがあります:thread_idpost_number。さらに、投稿が属するスレッドの ID であり、後者はスレッド内での位置です。確信が持てない場合は、行の下を確認してください。

私の問題は、SQLAlchemy に伝える方法がわからないことです

Postthread_id を使用して新しいインスタンスの追加をコミットするときは、tidthread_idtidが存在する投稿の数を調べ、その数から自動インクリメントします。


スキーマが良いアイデアだと思うのはなぜですか? それは自然でパフォーマンスが高いからです。

class Post(Base):
    number    = Column(Integer, primary_key=True, autoincrement=False, nullable=False)
    thread_id = Column(Integer, primary_key=True, autoincrement=False, nullable=False)
    title     = Column(Text) #nullable for not-first posts
    text      = Column(Text, nullable=False)
    ...
PAGESIZE = 10
#test
tid = 5
page = 4

スレッド全体 (クエリ):

thread5 = session.query(Post).filter_by(thread_id=5)

スレッドのタイトル:

title = thread5.filter_by(number=0).one().title

スレッドページ

page4 = thread5.filter(
    Post.number >= (page    * PAGESIZE),
    Post.number < ((page+1) * PAGESIZE)).all()
#or
page4 = thread5.offset(page * PAGESIZE).limit(PAGESIZE).all()

ページ数:

ceil(thread5.count() / PAGESIZE)
4

2 に答える 2

2

これは、SQL式をデフォルト値として使用して行うことができます(default引数を参照)。次のように呼び出し可能にします。

from sqlalchemy.sql import func

def maxnumber_for_threadid(context):
    return post_table.select([func.max(post_table.c.number)]).where(post_table.c.thread_id==context.current_parameters['thread_id'])

デフォルトの呼び出し可能オブジェクトからSQL式を返すことができるかどうかは絶対にわかりません。実際にこのクエリを実行し、コールバック内でスカラー値を返す必要がある場合があります。context(カーソルはパラメーターから使用できるはずです。)

ただし、@ kindallの言うことを実行し、number列に別の自動インクリメントシーケンスを使用することを強くお勧めします。あなたがやりたいことは、SQLAlchemyがなくても実際に正しく行うのは非常に難しいことです。たとえば、MVCCデータベースを使用しているthread_id場合は、トランザクションの実行中に一致する行の数が変更されないように、特別な行レベルのロックを導入する必要があります。これがどのように行われるかは、データベースに依存します。たとえば、MySQL InnoDBでは、次のようなことを行う必要があります。

BEGIN TRANSACTION;
SELECT MAX(number)+1 FROM posts WHERE thread_id=? FOR UPDATE;
INSERT INTO posts (thread_id, number) VALUES (?, ?); -- number is from previous query
COMMIT;

を使用しなかった場合FOR UPDATE、同じスレッドに同時に新しい投稿を挿入しようとする別の接続が、の同じ値を取得した可能性がありますnumber

したがって、追加のクエリとロックが必要なため、ポスト挿入はパフォーマンスが高くなるのではなく、実際には非常に遅くなります(比較的言えば)。

これはすべて、別のシーケンスを使用することで解決され、thread_id内でのみ投稿番号が増加することを心配する必要はありません。

于 2012-11-01T21:25:19.057 に答える
0

任意のスレッドの投稿に対してインクリメントするグローバル投稿番号を使用する必要があります。次に、特定のスレッドに使用する適切な数を把握する必要はありません。したがって、特定のスレッドには、7、20、42、51 などの番号が付けられた投稿がある場合があります。クエリから取得したレコードセットのサイズからスレッド内の投稿数を簡単に取得でき、実際の投稿番号とは別に HTML 出力内の投稿に簡単に番号を付けることができるため、これは問題ではありません。

于 2012-11-01T20:16:35.963 に答える