简体   繁体   English

对线索会话进行排序

[英]Sorting a threaded conversation

Not sure how to frame this one, but here goes. 不知道如何构建这个,但是这里。

It's a sorting algorithm question 这是一个排序算法问题

Tools I have to play with are PostgresSQL and python (2.6) on the server and javascript/jquery at the browser end 我必须使用的工具是服务器上的PostgresSQL和python(2.6)以及浏览器端的javascript / jquery

I need to move data that describes a threaded conversation from a postgres DB to a web page. 我需要将描述线索对话的数据从postgres DB移动到网页。 The data starts off in chronological order, I want to display in threads 数据按时间顺序开始,我想在线程中显示

Record numbers are small - should never be more than 100 messages returned 记录数量很小 - 不应该返回超过100条消息

So, as a simple example, imagine the table: 所以,作为一个简单的例子,想象一下表:

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

The end point I want to reach is 我想达到的终点是

  • Hello World 你好,世界
    • Hello Back 你好回来
    • Who are you? 你是谁?
      • Me of course 当然是我
  • Make me a sandwich 给我做一个三明治
    • No chance 没有机会

Or, to put it another way... 或者,换句话说......

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

I'm not after a full solution here, all the ajax, json and formatting stuff I'm happy to get on with. 我不是在这里完整的解决方案,所有的ajax,json和格式化的东西,我很乐意继续。

I'm just having issues getting my head around the neatest way to manage the sort. 我只是在解决管理排序的最佳方式时遇到了问题。

SQL? SQL? Python? 蟒蛇? Javascript? JavaScript的?

I'm currently playing with array sorts in Javascript (for no better reason than the fact that my python skills are exceptionally weak) 我目前正在使用Javascript中的数组排序(没有比我的python技能特别弱的事实更好的理由)

EDIT At the moment I'm at something like: 编辑目前我的情况如下:

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

And it's frustratingly close 这令人沮丧地接近

I've tried to do this in pure sql, because I think that's where the logic should belong. 我试图在纯sql中做这个,因为我认为这是逻辑应该属于的地方。 What you need to do is find the list of ids from parent to child, and order by that. 你需要做的是找到从父到子的id列表,并按顺序排序。 Luckily, postgres has array types which can be ordered, so we can use a recursive CTE: 幸运的是,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;

And the results: 结果如下:

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}"

I'm not sure how this will perform though, so you should definitely test and profile this on your real dataset to make sure it's fine. 我不确定这会如何表现,所以你一定要在你的真实数据集上测试和分析它,以确保它没问题。 If it's not, perhaps you could look at restructuring your data, and investigating different ways of storing "tree" data in a database. 如果不是,也许您可​​以考虑重构数据,并研究在数据库中存储“树”数据的不同方法。 There is a library for django called django-mptt that can efficiently store and retrieve trees. django有一个名为django-mptt的库,可以有效地存储和检索树木。 The concept applies to databases in general, but the algorithms for pulling out trees and making sure they stay intact require changes to your application logic, better handled by a library. 这个概念一般适用于数据库,但是用于提取树并确保它们保持完整的算法需要更改应用程序逻辑,更好地由库处理。

Edit: 编辑:

I should mention that I was originally using just the top-level id for "order_path" as a single number. 我应该提一下,我最初只使用“order_path”的顶级id作为单个数字。 This answer led me to using an array of ids to guarantee the order all the way down. 这个答案让我使用一系列ID来保证订单一直向下。

You could try something like this on JS side. 你可以在JS方面尝试这样的东西。 Since this have replies inside replies, it'd be easy to build a DOM from the convoSorted 由于回复内部有回复,因此从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);

I feel an idiot - I've been over-complicating this. 我觉得自己是个白痴 - 我一直过于复杂。

All it needed was a bit of lateral thinking (which this discussion has helped with) 所需要的只是一些横向思考(这个讨论有助于)

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

Sometimes I forget just what a powerful tool the dom is 有时我会忘记dom是一个强大的工具

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM