在這篇文章中,我想展示另一種處理相同問題的方法,但不使用圖形查詢,只使用我們?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ǎn)單結(jié)構(gòu)。
RavenDB 將確保每當(dāng)索引中的load()引用的文檔被更新時(shí),所有引用它的文檔都將被重新索引。在我們這里的情況下,每當(dāng)更新組時(shí),我們都會(huì)重新索引所有相關(guān)問題以匹配新的權(quán)限結(jié)構(gòu)。
RavenDB 的核心原則之一是您可以將更多工作推向索引并保持查詢快速和簡(jiǎn)單。這是一個(gè)很好的例子,說明我們?nèi)绾我砸环N非常優(yōu)雅的方式將工作推送到后臺(tái)索引的方式排列數(shù)據(jù)。