Аудит MongoDB с использованием потоков изменений в Java - PullRequest
0 голосов
/ 12 апреля 2019

Я пытаюсь проверять вставки, обновления и удаления в MongoDB. Поэтому я решил использовать приложение Java с потоками изменений и хранить результаты для каждой коллекции в собственной коллекции.

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

Я пытался использовать репозиторий Spring Mongo, но каждый раз, когда я сохраняю свой объект, репозиторий заменяет старый объект.

{doc=Document{{_id=5cb047d9e0da0e87342f5979, name=Testing Object, data=Document{{2019-04-12=0}}, _class=com.TestObject}}, time=2019-04-12T08:10:14, operation=replace}

Я также попытался создать собственное обновление, используя шаблон Монго.

private void update(TestObject testObject){
        MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
        MongoTemplate template = new MongoTemplate(mongoClient, "myDB");

        Query query = new Query(new Criteria("_id").is(testObject.getId()));
        Update update = new Update();
        update.set("name",testObject.getName());
        update.set("data", testObject.getData());
        template.upsert(query, update,TestObject.class);
}

На этот раз это было обновление и показывалось только обновленное поле, но я добавил только одно значение в поле данных, и оно показало все значения.

{new={"data": {"2019-04-12": {"$numberDecimal": "0"}, "2019-04-13": {"$numberDecimal": "1"}, "2019-04-14": {"$numberDecimal": "2"}}}, removed=[], time=2019-04-12T08:33:33, operation=update}

Есть ли способ получить только те пары ключ-значение, которые были добавлены / удалены?

Мой любимый результат будет:

{new={"data": "2019-04-14": {"$numberDecimal": "2"}}}, removed=[], time=2019-04-12T08:33:33, operation=update}

Мое приложение для аудита:

public static void main(String[] args) {
        MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");

        MongoDatabase database = mongoClient.getDatabase("myDB");
        MongoDatabase auditDb = mongoClient.getDatabase("audit");
        ChangeStreamIterable<Document> changeStreamDocuments = database.watch().fullDocument(FullDocument.DEFAULT);

        while (true) {
            ChangeStreamDocument<Document> doc = changeStreamDocuments.first();
            String collectionName = doc.getNamespace().getCollectionName();
            MongoCollection<Document> audit_collection = auditDb.getCollection("audit_" + collectionName);
            Map<String, Object> auditDoc = new HashMap<String, Object>();
            auditDoc.put("operation", doc.getOperationType().getValue());
            int date = doc.getClusterTime().getTime();
            LocalDateTime time = LocalDateTime.ofEpochSecond(date, 0, ZoneOffset.UTC);
            auditDoc.put("time", time);
            Document fullDocument = doc.getFullDocument();
            UpdateDescription updateDescription = doc.getUpdateDescription();
            if (fullDocument != null) { //insert
                auditDoc.put("doc", fullDocument);
            } else if (updateDescription != null) { //update
                auditDoc.put("new", updateDescription.getUpdatedFields());
                auditDoc.put("removed", updateDescription.getRemovedFields());
            } else { //delete
                auditDoc.put("doc", doc.getDocumentKey());
            }
            System.out.println(auditDoc);
            audit_collection.insertOne(new Document("document", auditDoc));
        }
}

Мой тестовый объект:

public class TestObject {

    @Id
    private ObjectId id;

    @Indexed(unique = true)
    private String name;

    private Map<String, Decimal128> data;

//Constructors, getter and setter would be below
}
...