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