2017-03-08 45 views
2

我有一個模型,看起來像這樣Ramda>貓鼬>的數據源操作

var TermSchema = new Schema({ 
group: {type:String}, 
key: {type:String}, 
translations:[{ 
    clientId:{type:Number,default:config.gdgId}, 
    lang:{type:String}, 
    val:{type:String}, 
    needsTrans:{type:Boolean,default:false} 
}], 
updatedAt:{type:Date, default: Date.now}, 
updatedBy:{type:String, default: ''}, 
createdBy:{type:String, default: ''}, 
createdAt:{type:String, default: Date.now}, 
comments:{type:String, default: ''}, 
softDelete:{type:Boolean,default: false} 

});

但我需要將特定客戶端翻譯的實例轉換爲lang> group> key> translation的i18n格式。我原來的代碼看起來像這樣

function companyTerms(clientId){ 
var deferred = q.defer(); 
var companyObj = {'en-US':{},'de-DE':{},'en-GB':{},'es-SP':{},'fr-FR':{},'it-IT':{},'nl-NL':{},'pt-BR':{},'zh-CN':{}}; 
Term.find({'translations':{$elemMatch:{'clientId':clientId}}, 'softDelete': false}, function(err,terms){ 
    _.each(terms,function(term){ 
     _.each(term.translations,function(trans){ 
     if(companyObj[trans.lang]){ 
      companyObj[trans.lang][term.group] = {}; 
     } 
     }) 
    }) 
    _.each(terms,function(term){ 
     _.each(term.translations,function(trans){ 
     if (trans.clientId == clientId && companyObj[trans.lang]) { 
      companyObj[trans.lang][term.group][term.key] = trans.val; 
     } 
     }) 
    }) 
    deferred.resolve(companyObj); 
    }) 
    return deferred.promise; 
    }  

Gross我知道了!

所以我一直在尋找方法來清理這些代碼/加快響應速度。我的第一次嘗試是使用具有輔助函數的Ramda庫。

function addToLang(groupObject){ 
let mapValues = obj => { 
    obj['group'] = groupObject['group'] 
    obj['key'] = groupObject['key'] 
    return obj 
    } 
    return R.map(mapValues, groupObject.translations) 

}

function companyTerms(clientId){ 
return Term.find({'translations':{$elemMatch:{'clientId':clientId}}, 'softDelete': false}) 
    .then(R.map(R.pick(['group','translations','key']))) 
    .then(R.map(addToLang))//Adds group field to each translation object 
    .then(R.flatten())//Flattens the different key objects 
    .then(R.filter(R.propEq('clientId',parseInt(clientId))))//Filters out non-client translations 
    .then(R.groupBy(R.prop('lang')))//Groups by language 
    .then(R.map(R.groupBy(R.prop('group'))))//Sub-groups by group 
    .then(R.map(R.map(R.groupBy(R.prop('key')))))//Has key as final group-value 
    .then(R.map(R.map(R.map(R.pick(['key'])))))//Removes all other meta-data 
} 

但我是由輔助功能惱火,並決定將剛跳進「總」的構造,看起來像這樣我的最終代碼。

function companyTerms(clientId){ 
return Term.aggregate([ 
    { 
    "$unwind":"$translations" 
    },{ 
    "$match":{ 
     "translations.clientId":parseInt(clientId), 
     "softDelete":false 
    } 
    },{ 
    "$project":{ 
     key:"$key", 
     group:"$group", 
     lang:'$translations.lang', 
    } 
    }]) 
    .then(R.groupBy(R.prop('lang')))//Groups by language 
    .then(R.map(R.groupBy(R.prop('group'))))//Sub-groups by group 
    .then(R.map(R.map(R.groupBy(R.prop('key')))))//Has key as final group-value 
    .then(R.map(R.map(R.map(R.pick(['key'])))))//Removes all other meta-data 
}; 

這不是比以前更簡潔,但它比以前快多了。

+2

這裏有問題嗎? –

+0

我的一般想法是徵求使這個功能更簡潔的想法 –

+0

您應該在問題中更清楚地說明。您應該可以編輯它來添加解釋。 –

回答

2

兩種可能性:

  • 如果你擔心的是幫手,因爲它不與代碼的其餘部分適合,這看起來(從一個角度,沒有任何數據來測試)像一個自由點,另類:

    R.lift(R.map)(R.compose(R.merge, R.pick(['group', 'key'])), R.prop('translations')) 
    
  • 你可能並不需要所有這些then秒。在第一次調用之後,它看起來不像是異步的。雖然將then連接在一起通常很方便,但隨着名單變長,它開始失去光彩。

    您可能只需將pipe函數放在一起並在單個then內調用組合。問題的關鍵是,只要f1f2 ... fn都是同步的,那麼這些是等價的:

    someAsyncFn() 
        .then(f1) 
        .then(f2) 
        .then(f3) 
        .then(f4) 
    

    someAsyncFn().then(pipe(f1, f2, f3, f4)) 
    

這些都不是驚天動地,但可能有助於清理代碼。

+0

謝謝斯科特,我會給它一個! –