2014-09-22 3 views
1

Я новичок в MongoDB. Я ищу способ зарегистрировать все операции, которые вставляют, обновляют или удаляют документы в целях сохранения истории изменений. Так, например, я хотел бы знать, когда было обновлено определенное поле в конкретном документе, что оно было обновлено и что было раньше. Это для приложения ASP.NET C# с использованием драйвера C# MongoDB, поэтому я не возражаю против того, включает ли это только сам Mongo или код C#.Запись, обновление и удаление операций в MongoDB

Пример:

ID |Timestamp |Operation|ObjectID |   PrevValue   |   NewValue 
----------------------------------------------------------------------------------------------- 
2153|1411390359| i |245245...|   null    |{name: "John Smith", age: 35} 
2154|1411390471| u |245245...|   {age: 35}   |   {age: 36} 
2155|1411390478| d |245245...|{name: "John Smith", age: 36}|   null 

Он не должен следовать этому точному формату, но он должен облегчить отслеживание истории.

Я взглянул на MongoDB oplog, но он, похоже, не подходит для такого рода работ. Чтобы определить изменения в документе, например, мне кажется, что я должен искать две записи (самая последняя запись обновления для документа и предыдущая запись документа, которая может быть обновлением или вставкой), а затем сравнить каждое поле в документе, чтобы проверить, какие из них были изменены и каковы их первоначальные значения. Я бы предпочел просто иметь одну запись, которая содержит всю эту информацию ради эффективности, в случае, если требуется много запросов для изучения изменений во многих документах. Я хочу убедиться, что использование журнала настолько безболезненным, насколько возможно. Было бы также идеально, если бы журнал был сохранен в коллекции MongoDB с документом для каждой записи (например, с помощью oplog), чтобы упростить запрос.

Есть ли функция в MongoDB (кроме oplog), которая может выполнить что-то вроде этого? Если нет, есть ли хороший сторонний инструмент, который может? Или я должен реализовать его вручную?

EDIT: Несколько подробнее:

1) Еще одна проблема, с oplog является то, что ограничен, поэтому он удаляет старые записи, когда он бежит из космоса. Я хотел бы сохранить список всю историю независимо от того, сколько ей лет.

2) Содержимое журнала будет отображаться каким-либо образом пользователю, который может запросить историю изменений. Это относится не только к внутренним записям администраторов БД, поэтому их необходимо запрашивать по требованию.

EDIT # 2: Я занимался мозговым штурмом некоторых решений этой проблемы, но все они все еще имеют некоторые недостатки, поэтому я был бы признателен за дальнейший ввод, если у кого-то есть лучшая идея.

Возможное решение 1: Ведение отдельного документа для каждой версии (с версией #) и флаг, если он был удален.

Реализация: добавьте поле «версия» к каждому документу. Версия 1 - это начальное состояние (представляет собой вставку), а последующие версии представляют собой обновления, которые помещаются в отдельные вновь созданные документы, а не обновляются старые. Версия -1 означает, что документ теперь считается «удаленным». Очевидно, что это не связано с фактическим файлом журнала.

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

Возможное решение 2: Ведение истории изменений для каждого документа в поле поддокументе

реализации: Каждый документ имеет поле «RevisionHistory», который содержит каждую ревизию с номером версии. Легче искать исторические данные для отдельных документов

Проблемы: сложнее выполнить поиск истории по нескольким документам, а любые вызовы API для выполнения обновлений сложнее из-за нового поля. В частности, мне нужно будет показать все изменения за прошлые X часов (X предоставлен пользователем) в рамках реализации, что потребует сканирования всех документов, если этот подход используется.

Возможное решение 3: Добавление вручную Вход вызова() из C#

Реализация: Каждый раз, когда MongoDB C# Driver API вызывается с новой операцией, есть программист также добавить строку призванию специальную функцию для ведения журнала в файл журнала.

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

Возможное решение 4: Создать функцию-оболочку для операций API из C#

реализации: Программисты не вызывать API напрямую, но вызвать функцию, которая обрабатывает работу за них. Это требует большой работы, обрабатывая все возможные типы вызовов API на уровне функции-оболочки, но является последовательным и надежным. Хороший способ абстрагировать доступ к БД, чтобы что-то не сломалось с неправильным вызовом API низкого уровня. Кто-то, не работающий над DAL, может просто вызвать функцию обертки, и функция определяет детали, включая ведение журнала.

Проблемы: Функция обертки более сложна для разработки, поскольку она требует учета всех возможных вызовов API, которые изменяют документ.

Сейчас я склоняюсь к решению 4. Но опять же, если есть более простой способ сделать это, мне интересно услышать его.

ответ

2

Нет. В MongoDB отсутствует функция 2.6. Стандартными параметрами отслеживания активности CRUD являются команда oplog и коллекция профилей запросов. Оба они ограничены и не достаточны для ваших целей. Oplog не сохраняет исходное состояние документа, просто инструкции по его установке в новое состояние: что-то вроде $inc будет изменено на $set в записи oplog. Если документ не изменяется дольше, чем окно закрытой коллекции, то его состояние до следующего изменения будет потеряно. Коллекция профилирования предназначена для мониторинга производительности и не сохраняет изменения в документах, а только запросы, которые были отправлены, поэтому, чтобы узнать, как запрос повлиял на состояние базы данных, вам также необходимо много узнать о состоянии базы данных в время выполнения запроса.

Я не знаю какого-либо стороннего инструмента для этого, так как знаю, что вам придется писать его самостоятельно. Вам нужно будет реализовать его как слой в вашем приложении, и доступ к MongoDB за пределами приложения не будет отслеживаться. Бремя для вашего приложения и его использование MongoDB будет большим. Может быть нереально создать что-то подобное.Например, предположим, что ваше приложение выдает обновление

> db.collection.update({ "t" : { "$gte" : 10 } }, { "$inc" : { "t.$" : -1 } }) 

Это находит все документы, в которых по крайней мере один элемент t массив больше, чем 9, а затем вычитает первый элемент массива больше, чем 9. Как вы собираетесь отслеживать изменения для этого обновления? Вы не можете, если только вы не выберете соответствующую находку перед обновлением, а затем либо выясните, какие изменения вы сами, либо найдите находку после обновления и перекрестные ссылки на результаты, чтобы выяснить изменения. Что делать, если приложение многопоточно? Такой подход не будет работать, если вы каким-либо образом не согласовываете все потоки.

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

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