2013-09-18 5 views
2

Не знаю, как будет звучать этот вопрос, но полагал, что я выбросить сигнал Bat все равно ... У меня есть набор данных, подобный следующему:CouchDB - «Выщипывание» документов ближайшего соседа из представления.

[ 
    { name: "Peter", score: 1000 }, 
    { name: "James", score: 800 }, 
    { name: "John", score: 600 }, 
    { name: "Saul", score: 400 }, 
    { name: "David", score: 200 } 
] 

В настоящее время существует несколько вещей, которые я как и с этой коллекцией, но основная функция, на которую я стремлюсь, - это взять данную запись и найти документы, которые сидят непосредственно над и под этим элементом в таблице баллов, например;

[ 
    { name: "James", score: 800 }, 
    -> { name: "John", score: 600 }, 
    { name: "Saul", score: 400 } 
] 

Я хотел бы также создать представление, которое выглядит следующим образом:

[ 
    { key: 1, value: { name: "Peter", score: 1000 } }, 
    { key: 2, value: { name: "James", score: 800 } }, 
    { key: 3, value: { name: "John", score: 600 } }, 
    { key: 4, value: { name: "Saul", score: 400 } }, 
    { key: 5, value: { name: "David", score: 200 } } 
] 

Я не могу помочь, но чувствую, что эти две проблемы связаны. Я также заинтересован в том, чтобы выполнить «выщипывание» в виде небольшого количества запросов REST, насколько это возможно ...

Я также с радостью принимаю решение, основанное на прикладном уровне, но опять же, я бы например, чтобы избежать нескольких поездок в БД, а также хотелось бы избежать вытащить больше данных, чем необходимо.

Любые идеи?

ответ

1

Вы можете создать представление, которое имеет оценку в качестве ключа. Функция карты просто должна выполнить emit(doc.score, null), где документ - документ, переданный функции. Если вы запрашиваете эту точку зрения с startkey=600, limit=2 и descending=false, вы получите документы с баллами 600 и 800. Если запрос с startkey=600, limit=2 и descending=true, вы получите документы с баллами 600 и 400.

Чтобы получить все документы в порядке убывания счета, вы просто запрашиваете с нисходящим = истинным и никакими другими параметрами. Конечно, вы не получите поле key: n, но вы можете легко добавить это в свой прикладной уровень.

+0

Это решение, которое я имею в виду. Я увлекаюсь «ключом: n», потому что я хочу избежать того, чтобы вытащить набор результатов из 1000 строк (или что-то еще), чтобы узнать, где «Питер» сидит в таблице. Еще одна вещь, которую я хотел бы сделать, - это вытащить документ по идентификатору и определить его рейтинг (и, возможно, выщипывать соседей), не возвращаясь к БД и не запросив свойство счета. Поэтому я пытаюсь подвести итог, насколько сложно, что все может быть ... Это разумно? – Charlie

+0

В общем случае вам нужно рассчитать свой «ключ» на уровне приложения, особенно если вы пытаетесь создать список рейтингов в реальном времени. Причина проста: представления обновляются инкрементально только для измененных документов. Если вы добавите Майка со счетом 1200, ваше представление будет обновляться только для этого документа, но другие остаются нетронутыми. Это может привести к неудобным результатам. – Kxepal

+0

@Charlie: Вы можете получить ключ: n, используя функцию списка сверху. –

1

Вы пытались использовать счет в качестве ключа? В этом случае вы можете создавать рейтинговые диаграммы и запросы для лиц, у которых есть оценка в некотором диапазоне. Ваша карта функция:

function(doc){ 
    emit(doc.score, {'name': doc.name, 'score': doc.score}) 
} 

// не уверен, что вы по-прежнему необходимо в таком значении

Теперь, если вы звоните ваш взгляд вы получите:

{ 
    "total_rows": 5, "offset": 0, "rows": [ 
    {"id": "1", "key": 200, "value": {"name": "David", "score": 200}}, 
    {"id": "2", "key": 400, "value": {"name": "Saul", "score": 400}}, 
    {"id": "3", "key": 600, "value": {"name": "John", "score": 600}}, 
    {"id": "4", "key": 800, "value": {"name": "James", "score": 800}}, 
    {"id": "5", "key": 1000, "value": {"name": "Peter", "score": 1000}} 
    ] 
} 

выглядит не так, как наивысшие рейтинги , Давайте добавим descending=true параметр запроса:

{"total_rows": 5, "offset": 0, "rows": [ 
    {"id": "5", "key": 1000, "value": {"name": "Peter", "score": 1000}}, 
    {"id": "4", "key": 800, "value": {"name": "James", "score": 800}}, 
    {"id": "3", "key": 600, "value": {"name": "John", "score": 600}}, 
    {"id": "2", "key": 400, "value": {"name": "Saul", "score": 400}}, 
    {"id": "1", "key": 200, "value": {"name": "David", "score": 200}} 
]} 

Хорошо! Теперь вы можете применить параметры запроса startkey/endkey для запроса информации в пределах указанного диапазона. Возьмем startkey=799&endkey=401. Следует отметить, что пограничные значения включены в ответ:

{"total_rows":5,"offset":2,"rows":[ 
    {"id":"3","key":600,"value":{"name":"John","score":600}} 
]} 

Результат будет запрос выглядит http://localhost:5984/db/_design/ddoc/_view/by_score?descending=true&startkey=799&endkey=401

-1

Я думаю, что я создать легкий вид набора данных (Испустите («оценка», нулевой), а предложенный Kxepal и Kim) вытащить его, кешировать и использовать фид изменений, чтобы он был свежим.

Таким образом, я бы больше не попадал в базу данных. Это должно сделать процесс «выщипывания» более простым, так как я могу явно добавить свойство «rank» к свойствам/элементам кешированного объекта и использовать его для создания вишневого материала.

Обновление:

Хотя выше, может работать в качестве решения (возможный случай использования Redis?), Используя TOTAL_ROWS вида отклика и значение смещения, делает извлечение документа «рангу» тривиальный (на основе «оценка», как было предложено в двух ответах выше) ...

Единственная проблема, которая по-прежнему остается, - это сама «выщипывание», которая может по-прежнему нуждаться в двух отдельных вызовах API, но это может быть не так уж плохо. ..

Все еще открыт для предложений.

Cheers. :)

+0

Что-то не так с этим? – Charlie

Смежные вопросы