Couchdb карта / уменьшить, чтобы вернуть сначала в потоке, а затем упорядочить по времени - PullRequest
0 голосов
/ 26 апреля 2011

У меня есть couchdb, который проводит серию событий. Каждое событие имеет владельца, идентификатор, время, когда оно произошло, и сообщение (плюс куча других вещей, которые не имеют значения для этого упражнения). Я хотел бы список событий, которые произошли недавно упорядочены по времени. Я просмотрел этот вопрос CouchDB - отфильтровать последний журнал для каждого зарегистрированного экземпляра из списка и попытался использовать его для сравнения с перелистыванием сравнения, чтобы сохранить первое сообщение (используя форму, в которой у меня есть сложный ключ).

К сожалению, это не совсем то, что нужно.

Вот моя функция карты

function(doc) {
  var owner, id;
  if (doc.owner
      && doc.stream_id
      && doc.message
      && doc.receipt_time)
    {
      emit([doc.owner,doc.stream_id,doc.receipt_time],
           { owner: doc.owner,
             stream_id: doc.stream_id,
             timestamp: doc.receipt_time,
             message: doc.message
           });
    }
}

и моя функция уменьшения

function(keys, values) {
  var challenger, winner = null;
  for (var a = 0; a < values.length; a++) {
      challenger = values[a];
      if (! winner) {
        winner = challenger;
      } else {
        if (winner.owner !== challenger.owner
            && winner.trace_id !== challenger.trace_id ) {
          return null;
        } else if (challenger.timestamp < winner.timestamp) {
          winner = challenger;
        }
      }
    }
  return winner;
}

Затем я вызываю с помощью? Убывающего = true & group = true & group_level = 2, чтобы получить первое сообщение из каждого потока, однако, кажется, что оно не упорядочено по времени, а по владельцу и stream_id, как это

{"rows":[
  {"key":["sam","a"],
   "value":
     {"owner":"sam","stream_id":"a","timestamp":1303754236482,"message":"foo"}
  },
  {"key":["sam","b"],
   "value":
     {"owner":"sam","stream_id":"b","timestamp":1303752578476,"message":"bar"}
  },
  {"key":["jim","j1"],
   "value":
     {"owner":"jim","stream_id":"j1","timestamp":1303625378839,"message":"stuff"}
  },
  {"key":["bob","loblaw"],
   "value":
     {"owner":"bob","stream_id":"loblaw","timestamp":1303328396532,"message":"more stuff"}
  },
  {"key":["anthony","foo"],
   "value":
     {"owner":"anthony","stream_id":"foo","timestamp":1303769699444,"message":"even more"}
  }
]}

(Обратите внимание, что последняя запись на самом деле является самой последней во времени).

Так что мне бы хотелось, чтобы окончательный вид был таким, какой он есть сейчас, но упорядочен по времени. Есть ли способ сделать это?

Ответы [ 3 ]

1 голос
/ 17 мая 2011

Хранить отметку времени stream_created_at в каждом сообщении.Так что за первое сообщение вы берете текущее время.Для каждого следующего сообщения в потоке вы копируете его из предыдущего (создайте представление, чтобы получить для этого stream_created_at_by_stream_id).

Затем создайте представление, которое отправляет:

[doc.owner,doc.stream_created_at, doc.stream_id, doc.receipt_time]

, которое будет группировать сообщенияиз одного потока вместе, сохраняя время упорядочения.stream.id обеспечит, чтобы сообщения из разных потоков не смешивались при одновременном создании двух потоков.И receive_time упорядочит сообщения в потоке по времени.

Так что в итоге вы получите Facebook, как разговоры.И вам вообще не нужна функция уменьшения.

0 голосов
/ 26 апреля 2011

Ну, я думаю, что на самом деле проще всего просто избежать этой проблемы.

Так как я управляю программным обеспечением, которое отправляет события, я только что добавил поле "start":true, в первый документ в потоке, затемФункция просмотра просто генерирует события с этим значением.

Это означает, что я не могу получить это для исторических данных, но это нормально, так как это в основном для проверки недавних потоков.

Другой вариант, который я попробовал, былдобавление функции списка, которая отправляет первый экземпляр каждого владельца stream_id, в представление с ключом [timestamp, owner, stream_id], однако, возникает проблема, заключающаяся в том, что при ограничении он не ограничивает окончательный отображаемый список, аисходный вид, поэтому дополнительный ключ работает лучше всего).

Я все еще хотел бы знать, есть ли способ сделать это с исходными данными.

0 голосов
/ 26 апреля 2011

Если я вас правильно понимаю, вы не хотите фильтровать коллекцию событий, а просто заказать их. Предполагая, что это правильно, решение на самом деле довольно простое, и вам даже не нужна функция приведения. Ключи, которые испускаются в вашей функции карты, используются для сортировки вида, сначала по тому, что находится в ключе, а затем до конца. Другими словами, если вы хотите отсортировать по stream_id, а тогда receive_time, ваш вызов emit будет выглядеть так:

emit([doc.stream_id,doc.receipt_time,doc.owner], doc.message);

Естественно, если вместо этого вы хотите отсортировать по квитанции по времени, а по потоку, ключом будет [doc.receipt_time,doc.stream_id,doc.owner]. Я не думаю, что есть необходимость включать что-либо в значение, которое уже присутствует в ключе, поэтому я сократил значение до просто сообщения.

...