2014-12-02 28 views
1

不知道如何框架这个,但在这里。排序线程对话

这是一个排序算法问题

工具我有玩的服务器和JavaScript/jQuery的在浏览器端

我需要移动数据对PostgreSQL的和python(2.6)描述螺纹从postgres数据库到网页的对话。该数据按照时间顺序开始了,我想在线程显示

创纪录的数字是小的 - 应该不会超过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 

终点我想达到的

  • 的Hello World
    • 你好回
    • 你是谁?
      • 我当然
  • 让我一个三明治
    • 没有机会

或者,换一种方式......

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); 

它很令人沮丧地关闭

+0

你可能会有所帮助:[图表](http://www.artfulsoftware.com/mysqlbook/sampler/mysqled1ch20.html)。 Postgres支持CTE,这使得这更容易。 – Dinesh 2014-12-02 00:39:34

+0

不确定您对“Reply_To”的阅读。如果仍然要收集数据,为什么不使用[SQL Fiddle](http://sqlfiddle.com/#!15/063f4/1/0)中的“Thread”列。由于没有关于应用程序上下文的更多上下文,这似乎使生活变得更容易。 – Abecee 2014-12-02 00:56:47

+0

对不起@Abecee总是很棘手,以决定包含多少信息,而不过分冗长 - 在这种情况下,我无法控制数据结构 - 我坚持给我的字段 – PerryW 2014-12-02 00:59:55

回答

2

我试过在纯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,可以有效地存储和检索树木。这个概念一般适用于数据库,但是抽出树并确保它们保持完好的算法需要对应用程序逻辑进行更改,更好地由库处理。

编辑:

我要指出,我本来只用顶级ID为“order_path”作为一个单一的数字。 This answer让我使用一个ID数组来保证顺序一路下降。

+0

这很整洁......我承认它现在正在伤害我的头,但它可能是这样的方式 – PerryW 2014-12-02 03:54:31

1

你可以在JS方面尝试这样的事情。由于这里面有答复的答复,它会很容易从convoSorted

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); 
+0

我喜欢它 - 此刻我正在尝试使用排序功能 - 我确信我只是离一些非常优雅的一步逻辑:) – PerryW 2014-12-02 03:48:13

+0

@PerryW让我们知道你想出什么。我很好奇,看看它如何作为排序功能来完成。 – artm 2014-12-02 09:51:36

+0

嗨@artm我正在接近(请参阅原始问题中的编辑),但后来发现了我在自己的答案中发布的尤里卡时刻 - 因为这是作为网页结束的,所以简单地使用DOM作为文件系统,根本不是排序问题 – PerryW 2014-12-02 21:42:22

0

我觉得白痴建立一个DOM - 我一直过于复杂这一点。

所有它需要的是一个有点横向思维(此讨论已与帮助)

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是什么