The database query log could be a crucial part of a database restoring process required after data corruption
caused by either an illegal update operation or a damage of database files. The main task here is to find the
right format for storing the queries.
The format should be targeted at programmatic data retrieving, and be minimalistic to keep the size of the audit
collection, that holds the query log, to a minimum. Also, it must contain additional information such as the time
of modification, or the collection name. You could imagine the following set of properties:
collection - the collection name
operation - the update operation name
timestamp - the time of modification
custom fields - to keep the data
Custom fields would depend on the update operation. For instance, for the 'insert' operation, only one
custom field must be stored - the 'object' field which contains an object that is being inserted into a collection,
this way the operation:
Let's have a look at the custom fields required to log all the available Java driver operations:
Operation
Object
'Criteria' object
'Sort' object
'Update' object
'Insert' flag
'Multi' flag
Add
+
Remove
+
Update
+
+
+
+
FetchAndRemove
+
+
FindAndModify
+
+
+
+
The number of optional fields is very limited and a lot of operations use the same objects
and flags, so a simple plain old object can be used to represent a log record in your application:
publicclassLogRecord{/** Database document. */protectedfinalBasicDBObjectdoc=newBasicDBObject();/** * Field names. */publicenumFields{/** Object id. */ID("_id"),/** Collection name. */COLLECTION("collection"),/** Database action. */ACTION("action"),/** Object to store. */OBJECT("object"),/** Search criteria. */CRITERIA("criteria"),/** 'Sort' object. */SORT("sort"),/** 'Update' object. */UPDATE("update"),/** 'Insert' flag. */INSERT("insert"),/** 'Multiple' flag. */MULTIPLE("multiple"),/** The time of modification. */TIME("time");privatefinalStringname;privateFields(finalStringname){this.name=name;}@OverridepublicStringtoString(){returnname;}}// Action Object Criteria Sort Update Insert Multiple// Add --// Remove --// Update -- -- -- --// FetchAndRemove -- --// FindAndModify -- -- -- --/** * Creates a log record. * * @param collection collection name * @param action database action * @param object object to store * @param criteria search criteria * @param sort 'sort' object * @param update 'update' object * @param insert 'insert' flag * @param multiple 'multiple' flag * @param time the time of modification */publicLogRecord(Stringcollection,Actionsaction,DBObjectobject,DBObjectcriteria,DBObjectsort,DBObjectupdate,booleaninsert,booleanmultiple,longtime){doc.append(Fields.COLLECTION.toString(),collection);doc.append(Fields.ACTION.toString(),action);doc.append(Fields.OBJECT.toString(),object);doc.append(Fields.CRITERIA.toString(),criteria);doc.append(Fields.SORT.toString(),sort);doc.append(Fields.UPDATE.toString(),update);doc.append(Fields.INSERT.toString(),insert);doc.append(Fields.MULTIPLE.toString(),multiple);doc.append(Fields.TIME.toString(),time);}/** * Returns the field value. * * @return the field value, or null if the value is not defined */publicObjectgetValue(Fieldsfield){doc.get(field.toString());}/** * Returns the database log document. * * @return the database log document */publicDBObjectgetDBObject(){return(DBObject)doc.clone();}}
Records stored in this way can be queried and read by humans, which gives sufficient debugging capabilities and, also,
can be converted to update queries during an automatic restoring process.
This post is written for the MongoDB Java driver version 2.4
If you're looking for a developer or considering starting a new project,
we are always ready to help!