js處理層級數據結構的一些總結


開發者對復雜的數據結構的處理能力也是體現開發者水平的一個度量吧。。。最近發現自己對一些嵌套數據結構、層級數據結構的處理能力不大足。。。經常被這些把自己繞暈。。。嚴重影響開發效率。。。就稍微低總結了一下下。。。

一、mongodb設計層級關系數據(這里主要說的是mongoose)

①假設有這樣的一個場景。某個文章下面有評論,每個評論可以被回復,每個回復又可以被回復...

首先,我們知道,普通的一對多的關系,可以通過引用,populate操作找出相應的引用對象,如:

var essaySchema = new mongoose.Schema({   //文章schema
    user:{
        type: mongoose.Schema.Types.ObjectId, //發布者的引用
        ref: 'user', //引用自User Model
        require: true //非空
    },
  ...
});

文章與評論的關系,就是一對多。自然也是按照這種處理方式即可。

但是,評論與回復的關系,就有點意思了。首先,評論和回復,回復與該回復的回復雖然是不同的東西(看着就拗口),但是這些的shema的信息都是由相同的字段構成。也就是說,可以說是自己嵌套了多個自己。

這個時候,就要這樣處理了:

//評論Schema定義
var commentSchema = new mongoose.Schema({
    content: {
        type: String, 
        require: true 
    },
    created: {
        type: Date, 
        "default": Date.now 
    },
    user: {
        type: mongoose.Schema.Types.ObjectId, //用戶的引用
        ref: 'user', //引用自User Model
        require: true //非空
    },
    subComment: [this], //自評論的類型為評論類型,也就是本身類型
});

最關鍵就是最后一句,實質上就是遞歸地引用了自身。查找的時候,也確實是需要根據上一層的subComment找到自己。套了深層的時候,查找的時候會容易繞暈,而且查找速度也會降低。建議做層級限制。

實踐小項目:一個簡單版node+express+mongodb的圖片分享

 

二、實際開發場景中的層級關系數據

①假設有這樣的一個場景,有一個商品數組,每個商品有兩個維度,顏色和規格。顏色和規格的組合會產生的sku(可以理解為每種組合情況的一個標識)數量為顏色數量*規格數量。當我們渲染完畢之后,顧客每切換一個規格,都要找到相應的sku。

設想一下,假如顧客每切換一個規格,我們就根據第幾個商品,切換的規格,沒有被切換的規格去查找。那么每次都是一個三重循環。。。

這種情況下,比較好的做法就是,初始化獲得數據的時候,建立三維數據,即Array[商品index][顏色][規格]。這樣每次切換,只要讀取相應的項就可以找到sku了。

但是,假若商品的維度不是二維,而是多維呢,而且不一定每種組合都存在這樣的商品的呢?

構造數據的方法,就顯得不大明智了,一是組合數過多,並不是每種組合商品都存在,而是循環太多重。

這個時候,又要利用對象去構造數據了。

第一步,根據展示需要構造。展示的時候,只需要知道,某個商品的某個維度是某個值即可。即:

var obj = {[
{'商品':'1',sku:'','維度1’:'...','維度2':'...',...}
]}

當點擊切換維度的時候,首先根據原來的維度信息,更新用戶新選的維度。遍歷該新的維度對象,與維度信息數據比較,如果一一相符則找到新的sku。然后再更新即可。  

在這里就要明確自己的"籌碼"與"目標",根據哪些東西,通過哪些途徑可以到達目標。將每一步拆分成一個小方法去做。。。

 

②假設有這樣的一個場景,首先要根據一些規則合並一些請求去請求不同的數據(即返回的數據,是多個參數結合在一起的,必須還要解析出數據原先的對應關系),然后獲得部分數據。再用獲得的部分數據中某條數據的參數去請求第二個接口。然后獲得不同的一些數據。

首先想到的可能是用promise處理,待兩個接口都請求完畢后再進行處理。但是假如,第一個接口獲得的是大部分主要的數據,第二個是小部分的數據。這個時候,等待第二個接口似乎就有點"不划算"了,特別是在用戶體驗上,當一個用戶打開某個頁面的時候,白屏就不好啦。  

這個時候,我們就要善於利用對象去構造符合我們的數據對象了。

我們可以這樣初始化一個對象:

var obj = { 
  '唯一的參數1'+‘_’+'唯一的參數1的id' : {
      第一次請求的數據 : [],
      第二次請求的數據 : [], 
    },
 '唯一的參數2'+‘_’+'唯一的參數2的id' : {
      第一次請求的數據 : [],
      第二次請求的數據 : [], 
    },
   ...
}

  總之,就是要找到唯一的東西,來構造對象。然后再根據這個唯一的值把相應的數據填上。好吧,我都說暈了。看個例子:

for(var i = 0;i < data.length; i++){
   for(var j = 0;j < data[i].params.length; j++){
        obj[data[i].groupId + '_' + data[i].params[j].pcId] = {};
   }
}

//請求數據回來后
for(var i = 0;i < data.length; i++){
   for(var j = 0;j < data[i].params.length; j++){
     obj[data[i].groupId + '_' + data[i].params[j].pcId][firstItem] = data[i].params[j].list; 
   }
}

//第二次數據回來后
for(var i = 0;i < data.length; i++){
   for(var j = 0;j < data[i].params.length; j++){
     obj[data[i].groupId + '_' + data[i].params[j].pcId][moreItem] = data[i].params[j].list; 
   }
}

  注意,如果是用vue,因為第二次請求的數據參數來自第一次,所以請二次數據回來之后,需要用全局api,set方法處理才會生效。

  

好吧。。。說了那么多,或許我自己明白自己在說啥。。。手動苦笑。。。 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM