CouchDB - иерархические комментарии с ранжированием. Стиль Хакер Ньюс
Я пытаюсь реализовать основной способ отображения комментариев так, как это предлагает Hacker News, используя CouchDB. Не только упорядоченно иерархически, но и каждый уровень дерева должен быть упорядочен переменной "точек".
Идея состоит в том, что я хочу, чтобы представление возвращало его в том порядке, за исключением, и не вызывало много вызовов Ajax, например, чтобы получить их и заставить их выглядеть так, как будто они упорядочены правильно.
Это то, что я получил до сих пор:
- Каждый документ является "комментарием".
- Каждый комментарий имеет свойство
path
, которое является упорядоченным списком, содержащим всех его родителей.
Так, например, представьте, что у меня есть 4 комментария (с _id 1
, 2
, 3
и 4
). Комментарий 2
является дочерним элементом 1
, комментарий 3
является дочерним элементом 2
, а комментарий 4
также является дочерним элементом 1
. Вот как выглядят данные:
{ _id: 1, path: ["1"] },
{ _id: 2, path: ["1", "2"] },
{ _id: 3, path: ["1", "2", "3"] }
{ _id: 4, path: ["1", "4"] }
Это хорошо работает для иерархии. Простой view
уже вернет вещи, упорядоченные так, как я хочу.
Проблема возникает, когда я хочу упорядочить каждый "уровень" дерева независимо. Так, например, документы 2
и 4
относятся к одной и той же ветки, но упорядочены на этом уровне по их идентификатору. Вместо этого я хочу, чтобы они упорядочивались на основе переменной "точек", которую я хочу добавить в этот путь, но не могут понять, где я могу добавить эту переменную, чтобы она работала так, как я ее хочу.
Есть ли способ сделать это? Учтите, что переменная "точки" со временем изменится.
Ответы
Ответ 1
Поскольку каждый уровень нужно сортировать рекурсивно по счету, Couch должен знать оценку каждого родителя, чтобы сделать эту работу так, как вы хотите.
Взяв ваш пример со следующими оценками (1:10, 2: 10, 3: 10, 4: 20)
В этом случае вы хотите, чтобы заказ выглядел следующим образом:
.1
.1.4
.1.2
.1.2.3
Вашему документу нужен массив баллов:
{ _id: 1, path: [1], scores: [10] },
{ _id: 2, path: [1, 2], scores: [10,10] },
{ _id: 3, path: [1, 2, 3], scores: [10,10,10] },
{ _id: 4, path: [1, 4], scores: [10,20] }
Затем вы будете использовать следующий вид сортировки в своем представлении.
emit([doc.scores, doc.path], doc)
путь используется как тай-брейк, потому что будут случаи, когда комментарии сиблинга имеют одинаковую оценку. Без тай-брейка их потомки могут потерять свою группировку (по цепочке родословной).
Примечание. Этот подход будет возвращать оценки от низкого до высокого, тогда как вам, вероятно, нужны оценки (от высокого до низкого) и пути/тай-брейка (от низкого до высокого). Поэтому обходным путем для этого было бы заполнение массива баллов инверсией каждого балла, как это:
{ _id: 1, path: [1], scores: [0.1] },
{ _id: 2, path: [1, 2], scores: [0.1,0.1] },
{ _id: 3, path: [1, 2, 3], scores: [0.1,0.1,0.1] },
{ _id: 4, path: [1, 4], scores: [0.1,0.2] }
и затем используйте descending=true
, когда вы запрашиваете представление.
Ответ 2
Может быть, кому-нибудь интересна тема по этому вопросу с вариантами решений:
http://mail-archives.apache.org/mod_mbox/couchdb-dev/201205.mbox/thread → тема "Иерархические комментарии Стиль хакерских новостей" 16/05/2012