Создание регистратора в CouchDB? - PullRequest
2 голосов
/ 25 августа 2010

Я хотел бы создать регистратор, используя CouchDB.По сути, каждый раз, когда кто-то обращается к файлу, я хотел бы записать в базу данных имя пользователя и время доступа к файлу.Если бы это был MySQL, я бы просто добавил строку для каждого доступа, соответствующего пользователю.Я не уверен, что делать в CouchDB.Нужно ли хранить каждый доступ в массиве?Тогда что мне делать во время обновления, есть ли способ добавить в документ?Будет ли у каждого пользователя свой документ?

Ответы [ 4 ]

1 голос
/ 26 августа 2010

Ответ Нильса идет по правильному пути с транзакциями. По его словам, вы захотите создавать разные документы для каждого доступа - думайте о них как о действиях. Вот как может выглядеть один из этих документов

{
  "_id": "32 char hash",
  "_rev": "32 char hash",
  "when": Unix time stamp,
  "by": "some unique identifier
}

Если вы отслеживали несколько файлов, вам нужно добавить поле «файл» и включить уникальный идентификатор.

Теперь мощь Map / Reduce начинает по-настоящему сиять, поскольку она чрезвычайно хороша для объединения нескольких фрагментов данных. Вот как можно получить общее количество просмотров:

Карта:

function(doc)
{
  emit(doc.at, 1);
}

Сокращение:

function(keys, values, rereduce)
{
  return sum(values);
}

Причина, по которой я добавил метку времени (doc.at) в ключ, заключается в том, что он позволяет нам получить общее количество просмотров за определенный промежуток времени. Например, /dbName/_design/designDocName/_view/viewName?startkey=1000&endkey=2000&group=true дает нам общее количество просмотров между этими двумя метками времени.

Приветствие.

1 голос
/ 28 августа 2010

Несмотря на то, что ответ Сэма - это хороший пример для подражания, я хотел бы отметить, что, действительно, есть хороший способ добавить документ Couch. Это пока не очень хорошо задокументировано.

Определяя функцию update в вашем проектном документе и используя ее для добавления к массиву внутри внутреннего документа, вы можете сэкономить значительное дисковое пространство. Кроме того, вы получите соотношение 1: 1 между файлом, к которому вы входите, и документом, который представляет этот файл. Вот как я могу представить документ: { "_id": "some/file/path/name.txt", "_rev": "32 char hash", "accesses": [ {"at": 1282839291, "by": "ben"}, {"at": 1282839305, "by": "kate"}, {"at": 1282839367, "by": "ozone"} ]<br> }

Одно предостережение: вам нужно будет закодировать "/" как% 2F, когда вы запросите его у CouchDB, или вы получите ошибку. Использование слешей в идентификаторах документов вполне нормально.

А вот пара функций отображения / уменьшения: function(doc) { if (doc.accesses) { for (i=0; i < doc.accesses.length; i++) { event = doc.accesses[i]; emit([doc._id, event.by, event.at], 1); } } } function(keys, values, rereduce) { return sum(values); }

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

GET <a href="http://127.0.0.1:5984/dbname/some%2Ffile%2Fpath%2Fname.txt" rel="nofollow noreferrer">http://127.0.0.1:5984/dbname/some%2Ffile%2Fpath%2Fname.txt</a>

Если вы хотите посчитать, сколько раз каждый файл был доступен каждому пользователю, вы запросите представление следующим образом:

GET <a href="http://127.0.0.1:5984/test/_design/touch/_view/log?group_level=2" rel="nofollow noreferrer">http://127.0.0.1:5984/test/_design/touch/_view/log?group_level=2</a>

Используйте group_level = 1, если вы просто хотите подсчитать общее количество обращений на файл.

Наконец, вот функция update, которую вы можете использовать для добавления в этот массив doc.accesses: function(doc, req) { var whom = req.query.by; var when = Math.round(new Date().getTime() / 1000);</p> <p>if (!doc.accesses) doc.accesses = []; var event = {"at": when, "by": whom} doc.accesses.push(event); var message = 'Logged ' + event.by + ' accessing ' + doc._id + ' at ' + event.at; return [doc, message]; }

Теперь, когда вам нужно зарегистрировать доступ к файлу, отправляйте запрос, подобный следующему (в зависимости от того, как вы называете свой проектный документ и функцию обновления):

<a href="http://127.0.0.1:5984/my_database/_design/my_designdoc/_update/update_function_name/some%2Ffile%2Fpath%2Fname.txt?by=username" rel="nofollow noreferrer">http://127.0.0.1:5984/my_database/_design/my_designdoc/_update/update_function_name/some%2Ffile%2Fpath%2Fname.txt?by=username</a>

1 голос
/ 26 августа 2010

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

  • Файлы журналов / документы имеют тенденцию к росту . Вы не хотите отправлять большие документы по сети для каждой новой добавляемой вами записи.
  • Файлы журналов / документы обычно обновляются . Если все записи журнала хранятся в одном документе, и вы пытаетесь записать много одновременных записей журнала, вы можете столкнуться с несоответствием версий документа при обновлении.

Ваше предложение пользовательских документов звучит как хорошее решение, поскольку оно будет держать документы маленькими. Кроме того, маловероятно, что один пользователь сгенерирует одновременные записи в журнале, сводя к минимуму любые условия гонки.

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

0 голосов
/ 03 декабря 2013

Комментарий к двум последним ответам состоит в том, что они ссылаются на CouchBase, а не на Apache CouchDb.Однако можно определить обработчики обновлений в CouchDb, но я не использовал его.http://wiki.apache.org/couchdb/Document_Update_Handlers

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...