0

私のアプリケーションでTrelloのようなkanbanアジャイルボードを実装しようとしています。私はそれを最善の方法でやる方法が不思議です。私はこれらのエンティティを検討している:KanBanデータベースアーキテクチャ


多くのリスト

を持って
リストは、私が「しかしカード
は、いくつかのコンテンツ

が含まれている多くのカード

を持っていますカードの注文につかまった。各カードは、リスト内で特定の順序でカードを並べ替えるソート位置を持つ必要があります。カードをドラッグするときに、カードの位置を変更してデータベースに保存する必要があります。これを行う最も効率的な方法は何ですか?

カードを別の位置(何百ものカードがあります)にドラッグした後、List(または2)のすべてのカードの位置を再計算する必要があるため、各カードにpositionフィールドを追加するのは冗長です。私はリストにすべてのカードIDの配列を格納し、この配列でカードをソートすることを考えていました。このソリューションの賛否両論は何ですか?そしてもっと良い解決策はありますか?

私はRuby on RailsとPostgreSQLを使用しています。私は、次の解決策を考え出した@cske答え使用

UPDATE

CREATE OR REPLACE FUNCTION move_buyer_card(
    new_list_id INT 
    , param_id  INT 
    , new_position INT 
) RETURNS FLOAT4 
LANGUAGE plpgsql SECURITY DEFINER 
AS $$ 
DECLARE 
    var_lower_bound FLOAT4; 
    var_upper_bound FLOAT4; 
    var_new_weight FLOAT4; /*between 0 and 1*/ 
BEGIN 
    IF new_position < 2 THEN /*first position*/ 
    var_lower_bound := 0; 
    SELECT MIN(weight) FROM Buyers 
     WHERE board_list_id = new_list_id 
     INTO var_upper_bound; 
    IF var_upper_bound IS NULL THEN /*empty list*/ 
     var_upper_bound := 1; 
    END IF; 
    ELSE /*not first position*/ 
    WITH ordered_cards AS (
     SELECT id, RANK() OVER (ORDER BY weight ASC) AS rank, weight 
     FROM Buyers WHERE board_list_id = new_list_id 
    ) 
    SELECT cards0.weight, cards1.weight from ordered_cards cards0 
     JOIN ordered_cards cards1 
     ON cards0.rank = cards1.rank - 1 
     WHERE cards1.rank = new_position 
     INTO var_lower_bound, var_upper_bound; 
    IF NOT FOUND THEN /*only 1 item in list OR last position*/ 
     SELECT MAX(weight) FROM Buyers WHERE board_list_id = new_list_id 
     INTO var_lower_bound; 
     IF var_lower_bound IS NULL THEN /*empty list*/ 
     var_lower_bound := 0; 
     END IF; 
     var_upper_bound := 1; 
    END IF; 
    END IF; 
    var_new_weight := var_lower_bound + (var_upper_bound - var_lower_bound)/2; 
    UPDATE Buyers 
    SET weight = var_new_weight, 
     board_list_id = new_list_id 
    WHERE id = param_id; 
    RETURN var_new_weight; 
END; 
$$; 

答えて

1

はこのことを考えてみましょうが、トリックは位置を保存するのではなく、重量が、あなたは、任意の2つの間に挿入することができますので、要素

create table listOfCards (
    listId INTEGER 
    ,cardId INTEGER 
    ,weigth FLOAT4 
    ,PRIMARY KEY (listId,cardId) 
); 

CREATE OR REPLACE FUNCTION addCard(
    plistId INT 
    , pcardId INT 
    , ppos INT 
) RETURNS FLOAT4 
LANGUAGE plpgsql SECURITY DEFINER 
AS $$ 
DECLARE 
    vlb FLOAT4; 
    vub FLOAT4; 
    vnw FLOAT4; 
BEGIN 
    IF 2 > ppos THEN 
    vlb := 0; 
    SELECT min(weigth) FROM listOfCards WHERE listId = plistId INTO vub; 
    IF vub IS NULL THEN /*empty list*/ 
     vub := 2; 
    END IF; 
    ELSE 
    with corder as (select cardId,RANK() OVER (order by weigth asc) as r,weigth FROM listOfCards WHERE listId=1) 
    select c0.weigth,c1.weigth from corder c0 JOIN corder c1 ON c1.r = c0.r + 1 where c1.r = ppos INTO vlb,vub; 
    IF NOT FOUND THEN 
     SELECT max(weigth) FROM listOfCards WHERE listId = plistId INTO vlb; 
     IF vlb IS NULL THEN /*empty list*/ 
     vlb := 0; 
     END IF; 
     vub := (vlb+1) * 2; 
    END IF; 
    END IF; 
    vnw := vlb + (vub-vlb) /2; 
    INSERT INTO listOfCards(listId, cardId, weigth) 
     VALUES (plistId,pcardId,vnw) 
    ON CONFLICT ON CONSTRAINT listofcards_pkey DO UPDATE SET weigth = vnw ; 
    RETURN vnw; 
END; 
$$; 

使用法:

select addCard(1,1,1); 
select addCard(1,2,1); 
select addCard(1,3,2); 
select addCard(1,4,2); 
select addCard(1,5,5); 
select addCard(1,5,2); 

select * from listOfCards ORDER BY weigth; 

結果:あなたの答えのための 1,2,0.5 1,5,0.5625 1,4,0.625 1,3,0.75 1,1,1

+0

感謝。それは実用的な解決策です。少し修正されたコードで私の質問を更新しました - あなたはそれについてコメントできますか?私のソリューションは少しシンプルです(混乱しない数字)。 – leemour

+0

@leemourこれは単純です(あなたのコードではparam_idが既にバイヤーにありますが(最後に更新)チェックはしません)、適切なテストケースを忘れないでください(空リスト、単一要素リスト内での移動、 ...)、テーブル構造が質問に表示されない詳細を伝えるのが難しい – cske

+0

はい、私はすべてのエッジケースに対してバージョンを完全にテストしました。あなたのソリューションは最後のアイテムのウェイトを1に設定し、その後アイテムを追加するとウェイトを1より大きい値に設定します。それを考慮に入れてソリューションを更新してもよろしいですか?私は 'vub:= 2;を' vub:= 1; '、' ON c1.r = c0.r + 1'に 'ON c0.r = c1.r - 1'と' vub:=(vlb +1)* 2; 'vub:= 1' – leemour

関連する問題