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, когда вы запрашиваете представление.