在這篇文章中,我想展示另一種處理相同問題的方法,但不使用圖形查詢,只使用我們在 RavenDB 4.1 中的功能。
這個想法是,給定一個用戶,我希望能夠?qū)υ撚脩粲袡?quán)訪問的所有問題發(fā)出查詢,要么直接(如圖中的 Sunny),要么通過一個組(如 Max,通過 project-x 組) ) 或通過遞歸組,例如 (Nati,通過 project-x –> team-nati 組)。
從這篇文章的名稱可以想象,這需要遞歸。您可以閱讀有關(guān)此的文檔,但我想增加一些趣味并同時使用多個功能。
我們來看下面的索引(Issues/Permissions):
// Issues/Permissions index definition
map("Issues", issue =>{
var groups = issue.Groups.reduce(recurse_groups, {});
return { Groups: Object.keys(groups), Users: issue.Users };
});
function recurse_groups(accumulator, grpId) {
if(grpId == null || accumulator.hasOwnProperty(grpId))
return accumulator;
accumulator[grpId] = null;
var grp = load(grpId, "Groups");
if(grp == null || grp.Parents == null)
return accumulator;
return grp.Parents.reduce(recurse_groups, accumulator);
}
這是一個 JS 索引,它在 Issues 集合上有一個 map() 函數(shù)。對于每個問題,我們?yōu)閱栴}的用戶和允許訪問它的組(遞歸地)編制索引。
對于圖中的問題,此索引的輸出如下:
現(xiàn)在讓我們看看如何查詢這個。
這個查詢有兩個子句;要么直接分配給我們,要么通過一個小組分配給我們。這里的關(guān)鍵是在recurse_groups () 和里面,索引中的load()調(diào)用。它向上掃描定義的組及其父級,直到我們在索引中有一個易于搜索的簡單結(jié)構(gòu)。
RavenDB 將確保每當索引中的load()引用的文檔被更新時,所有引用它的文檔都將被重新索引。在我們這里的情況下,每當更新組時,我們都會重新索引所有相關(guān)問題以匹配新的權(quán)限結(jié)構(gòu)。
RavenDB 的核心原則之一是您可以將更多工作推向索引并保持查詢快速和簡單。這是一個很好的例子,說明我們?nèi)绾我砸环N非常優(yōu)雅的方式將工作推送到后臺索引的方式排列數(shù)據(jù)。