增加數(shù)據(jù)操作日志記錄

需求:API接口--【SaaS后臺(tái)】增加數(shù)據(jù)操作日志記錄

目前做的

實(shí)現(xiàn)過(guò)程

1.service中調(diào)用


  1. 異步處理數(shù)據(jù)及存儲(chǔ)

2.1數(shù)據(jù)處理(展示替換)

2.2數(shù)據(jù)處理(數(shù)據(jù)對(duì)比)

/**
     * 對(duì)比節(jié)點(diǎn)數(shù)據(jù)
     *
     * @param oldNode          舊節(jié)點(diǎn)數(shù)據(jù)
     * @param newNode          新節(jié)點(diǎn)數(shù)據(jù)
     * @param operationDetails 操作詳情列表
     */
    private void compareJsonNodes(JsonNode oldNode, JsonNode newNode, List<OperationDetails> operationDetails) {
        // 檢查兩個(gè)節(jié)點(diǎn)是否都是數(shù)組
        if (oldNode.isArray() && newNode.isArray()) {
            int minSize = Math.min(oldNode.size(), newNode.size());
            for (int i = 0; i < minSize; i++) {
                compareJsonNodes(oldNode.get(i), newNode.get(i), operationDetails);
            }
            for (int i = minSize; i < oldNode.size(); i++) {
                compareJsonNodes(oldNode.get(i), createEmptyNode(oldNode.get(i)), operationDetails);
            }
            for (int i = minSize; i < newNode.size(); i++) {
                compareJsonNodes(createEmptyNode(newNode.get(i)), newNode.get(i), operationDetails);
            }
            return;
        }
        List<SysOperationLogTrackEnum> childNodes = getChildNodes();
        Iterator<Map.Entry<String, JsonNode>> newFields = newNode.fields();
        // 處理新數(shù)據(jù)中的字段
        while (newFields.hasNext()) {
            Map.Entry<String, JsonNode> entry = newFields.next();
            String fieldName = entry.getKey();
            Optional<SysOperationLogTrackEnum> operationLogTrackEnum = childNodes.stream()
                    .filter(r -> r.getColumnName().equals(fieldName))
                    .findFirst();
            if (operationLogTrackEnum.isPresent()) {
                SysOperationLogTrackEnum sysOperationLogTrackEnum = operationLogTrackEnum.get();
                JsonNode newValue = entry.getValue();
                JsonNode oldValue = oldNode.get(fieldName);
                if ((newValue == null || newValue.isNull()) && (oldValue != null && !oldValue.isNull())) {
                    OperationDetails operationDetail = sysOperationLogTrackEnum.replaceValues(
                            fieldName, handleJsonNode(oldValue), null
                    );
                    operationDetails.add(operationDetail);
                } else if (oldValue == null || oldValue.isNull() && (newValue != null && !newValue.isNull())) {
                    OperationDetails operationDetail = sysOperationLogTrackEnum.replaceValues(
                            fieldName, null, handleJsonNode(newValue)
                    );
                    operationDetails.add(operationDetail);
                } else if (oldValue.equals(newValue)) {
                } else if (!sysOperationLogTrackEnum.getChildNodes().isEmpty()) {
                    sysOperationLogTrackEnum.compareJsonNodes(oldValue, newValue, operationDetails);
                } else {
                    OperationDetails operationDetail = sysOperationLogTrackEnum.replaceValues(
                            fieldName, handleJsonNode(oldValue), handleJsonNode(newValue)
                    );
                    operationDetails.add(operationDetail);
                }
            }
        }
    }

存在的疑問(wèn)

1.不可避免的需要數(shù)據(jù)對(duì)比,這種方式是否可行
2.誰(shuí)來(lái)定義哪些字段需要對(duì)比
3.需要默認(rèn)展示方式如何展示,使用參數(shù)占位符如何展示

待優(yōu)化

刪除原始數(shù)據(jù)的存儲(chǔ)
異步線程池進(jìn)行存儲(chǔ)
參數(shù)占位符入?yún)⒄故?br> 空間換時(shí)間把子節(jié)點(diǎn)數(shù)據(jù)做成hashMap存儲(chǔ)減少時(shí)間復(fù)雜度
可以添加一個(gè)操作對(duì)象字段
可以把展示的方式改成一句話
展示時(shí)可以進(jìn)行對(duì)比標(biāo)記新增或刪除的內(nèi)容

假設(shè)

在只有兩層遞歸結(jié)構(gòu)的情況下,如果第一層包含數(shù)組,且每層大約有 10 個(gè)字段,我們可以更具體地計(jì)算時(shí)間復(fù)雜度。

  • 第一層有一個(gè)數(shù)組,數(shù)組長(zhǎng)度為 n。
  • 每個(gè)數(shù)組元素是一個(gè) JSON 對(duì)象,包含大約 10 個(gè)字段。
  • 第二層遞歸處理這些 JSON 對(duì)象中的字段。

分析

1. 第一層數(shù)組處理

  • 數(shù)組長(zhǎng)度為 n。
  • 對(duì)數(shù)組中的每個(gè)元素,調(diào)用 compareJsonNodes 處理其內(nèi)部的 JSON 對(duì)象。由于數(shù)組長(zhǎng)度為 n,這一層的時(shí)間復(fù)雜度為 O(n)。

2. 第二層字段處理

  • 假設(shè)每個(gè) JSON 對(duì)象包含 k 個(gè)字段(在你的例子中 k ≈ 10)。
  • 處理每個(gè)字段時(shí),可能需要對(duì) childNodes.stream().filter(...).findFirst() 進(jìn)行線性搜索。假設(shè) childNodes 的大小為 m,則對(duì)每個(gè)字段的處理時(shí)間為 O(m)
  • 第二層遞歸的復(fù)雜度為 O(k * m)。由于 k ≈ 10,可以視為常數(shù),復(fù)雜度為 O(m)

綜合計(jì)算

  • 第一層的時(shí)間復(fù)雜度是 O(n)。
  • 每個(gè)數(shù)組元素在第二層的時(shí)間復(fù)雜度為 O(m),由于有 n 個(gè)元素,總體時(shí)間復(fù)雜度為 O(n * m)。

總時(shí)間復(fù)雜度

在這種情況下,代碼的總時(shí)間復(fù)雜度為 O(n * m),其中:

  • n 是第一層數(shù)組的長(zhǎng)度。
  • mchildNodes 的大小。

由于 k ≈ 10,這個(gè)部分基本可以視為常數(shù),不影響整體的時(shí)間復(fù)雜度計(jì)算。


a. 測(cè)試不同 n 值的性能表現(xiàn),驗(yàn)證 O(n * m) 的實(shí)際影響。
b. 考慮優(yōu)化 childNodes 搜索部分,減少 m 的影響。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容