[英]Sorting a threaded conversation
不知道如何構建這個,但是這里。
這是一個排序算法問題
我必須使用的工具是服務器上的PostgresSQL和python(2.6)以及瀏覽器端的javascript / jquery
我需要將描述線索對話的數據從postgres DB移動到網頁。 數據按時間順序開始,我想在線程中顯示
記錄數量很小 - 不應該返回超過100條消息
所以,作為一個簡單的例子,想象一下表:
ID Reply_To Text
=== ======== =============================
1 0 Hello World
2 0 Make me a sandwich
3 1 Hello back
4 2 No chance
5 1 Who are you?
6 5 Me of course
我想達到的終點是
或者,換句話說......
ID Reply_To Text
=== ======== =============================
1 0 Hello World
3 1 Hello back
5 1 Who are you?
6 5 Me of course
2 0 Make me a sandwich
4 2 No chance
我不是在這里完整的解決方案,所有的ajax,json和格式化的東西,我很樂意繼續。
我只是在解決管理排序的最佳方式時遇到了問題。
SQL? 蟒蛇? JavaScript的?
我目前正在使用Javascript中的數組排序(沒有比我的python技能特別弱的事實更好的理由)
編輯目前我的情況如下:
function byThread(a,b) {
if (a.reply > b.id && a.reply != 0){
console.log("Compared id=" + a.id + " with id=" + b.id + " and returned -1 ")
return -1;
}
if (a.id > b.reply && b.reply != 0 ){
console.log("Compared id=" + a.id + " with id=" + b.id + " and returned 1 ")
return 1;
}
console.log("Compared id=" + a.id + " with id=" + b.id + " and returned 0 ")
return 0;
}
msg.sort(byThread);
這令人沮喪地接近
我試圖在純sql中做這個,因為我認為這是邏輯應該屬於的地方。 你需要做的是找到從父到子的id列表,並按順序排序。 幸運的是,postgres有可以訂購的數組類型,所以我們可以使用遞歸CTE:
with recursive threaded(id, reply_to, message, order_path) as (
select
parent.id,
parent.reply_to,
parent.message,
NULL::int[] || parent.id -- create an 1-element array with the parent id
from conversation parent
where parent.reply_to is null
UNION ALL
select
reply.id,
reply.reply_to,
reply.message,
t.order_path || reply.id -- append the reply id to the current path
from threaded t
join conversation reply on t.id = reply.reply_to
where reply.reply_to is not null
)
select * from threaded order by order_path;
結果如下:
1 NULL "Hello World" "{1}"
3 1 "Hello Back" "{1,3}"
5 1 "Who are you?" "{1,5}"
6 5 "Me of course" "{1,5,6}"
2 NULL "Make me a sandwich" "{2}"
4 2 "No Chance" "{2,4}"
我不確定這會如何表現,所以你一定要在你的真實數據集上測試和分析它,以確保它沒問題。 如果不是,也許您可以考慮重構數據,並研究在數據庫中存儲“樹”數據的不同方法。 django有一個名為django-mptt的庫,可以有效地存儲和檢索樹木。 這個概念一般適用於數據庫,但是用於提取樹並確保它們保持完整的算法需要更改應用程序邏輯,更好地由庫處理。
編輯:
我應該提一下,我最初只使用“order_path”的頂級id作為單個數字。 這個答案讓我使用一系列ID來保證訂單一直向下。
你可以在JS方面嘗試這樣的東西。 由於回復內部有回復,因此從convoSorted
構建DOM很容易
var convo = [{id: 1, replyTo: 0, text: "hello world"},
{id: 2, replyTo: 0, text: "Make me a sandwich"},
{id: 3, replyTo: 1, text: "hello back"},
{id: 4, replyTo: 2, text: "no chance"},
{id: 5, replyTo: 1, text: "who are you?"},
{id: 6, replyTo: 5, text: "me of course"},
{id: 7, replyTo: 0, text: "new question"},
{id: 8, replyTo: 7, text: "new answer"}];
var convoSorted = [];
function addToReplies(obj, rply){ //recursive function to find the q. to reply to.
if (obj.id == rply.replyTo){
obj.replies.push({id: rply.id, text: rply.text, replies: []}); //add to the replies array
}
else{
for (k = 0; k < obj.replies.length; k++){
addToReplies(obj.replies[k], rply);
}
}
}
function sortConvo(){
for (i = 0; i < convo.length; i++){
if (convo[i].replyTo == 0){ //if it's not a reply, add to sorted array
convoSorted.push({ id : convo[i].id, text: convo[i].text, replies: [] });
}
else{ //it's a reply, find the question it's replying
for (j = 0; j < convoSorted.length; j++){
addToReplies(convoSorted[j], convo[i]);
}
}
}
}
sortConvo();
console.log(convoSorted);
我覺得自己是個白痴 - 我一直過於復雜。
所需要的只是一些橫向思考(這個討論有助於)
msgs=[
{id:1,reply:0,msg:'Hello World'},
{id:2,reply:0,msg:'Make me a sandwich'},
{id:3,reply:1,msg:'Hello back'},
{id:4,reply:2,msg:'No chance'},
{id:5,reply:1,msg:'Who are you?'},
{id:6,reply:5,msg:'Me of course'}
];
msgs.sort(function(a,b){
return a.reply - b.reply;
});
var conversation=$("<div id='threaded'>");
var list = $("<ul>")
.attr("id","thread_" + msgs[0].reply);
var message = $("<li>")
.text(msgs[0].msg)
.attr("id","msg_" + msgs[0].id);
$(list).append(message);
$(conversation).append(list);
for (i=1; i<msgs.length; i++){
var message = $("<li>")
.text(msgs[i].msg)
.attr("id","msg_" + msgs[i].id);
if ($(conversation).find("#msg_" + msgs[i].reply).length == 0){
$(conversation).find("ul:eq(0)").append(message);
} else {
var list = $("<ul>")
.attr("id","thread_" + msgs[i].id);
$(list).append(message);
$(conversation).find("#msg_" + msgs[i].reply).append(list);
}
}
有時我會忘記dom是一個強大的工具
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.