[英]How to get nested documents in FaunaDB?
要在 Fauna 中獲取單個文檔,我們會:
q.Get(q.Ref(q.Collection('posts'), '192903209792046592'))
我們得到類似的東西:
{
data: {
title: 'Lorem ipsum',
authorId: '892943607792046595'
}
}
是否可以在同一個查詢中獲取帖子和作者?
像這樣的東西:
{
data: {
title: 'Lorem ipsum',
author: {
name: 'John Doe'
}
}
}
由於這是一個常見問題,我將對其進行擴展,並為您提供入門所需的所有信息。 我最近寫了一個例子,很快也會詳細說明這一點。
我將逐步構建查詢以盡可能地進行教育假設..我們編寫了一個 twitter 之類的應用程序並想要檢索推文。 我們要做的第一件事就是獲取推文列表。
Paginate(Documents(Collection('fweets')))
它返回參考列表
Paginate(Documents(Index('some_index')))
它返回您在創建索引時選擇的所有值,例如: [[value1, value2], ...]
這將返回一個參考頁面,或者本質上是一個參考列表。
然后你做你在你的問題中所做的,你通過映射它來獲取參考Map (和 Map 將是你的主力來回答你的問題,因為我們進一步 go)
Map(
Paginate(Documents(Collection('fweets'))),
Lambda('ref', Var('ref'))
)
您可以使用與我們在文檔中獲取參考文獻 map 完全相同的技術。 只有現在我們才會對指向其他 collections 的引用執行 Get。 想象一下,我的每條推文中都有一個作者,讓我們得到那個作者。 我們將逐步使用用戶Let來構造我們的查詢和 go 讓我們首先用 Let 重構我們的查詢
Map(
Paginate(Documents(Collection('fweets'))),
// and in this function, the magic will happen, for now we just return the tweet.
Lambda('f',
Let({
fweet: Get(Var('f'))
},
Var('fweet')
)
)
)
我們現在將添加一行來獲取作者。
Map(
Paginate(Documents(Collection('fweets'))),
// and in this function, the magic will happen
Lambda('f',
Let({
fweet: Get(Var('f')),
author: Get(Select(['data', 'author'], Var('fweet'))), // we get the author reference
},
// And now we return a nested doc
{
fweet: Var('fweet'),
author: Var('author')
}
)
)
)
這將返回:
[{
"fweet": {
< your tweet data >
},
"author": {
< your author data >
}
}, ... ]
現在我們有了這個結構,添加一些額外的東西很容易。 想象一下,我們還有一條“資產”推文鏈接到我們在推文中存儲參考的推文
Map(
Paginate(Documents(Collection('fweets'))),
Lambda('f',
Let({
fweet: Get(Var('f')),
author: Get(Select(['data', 'author'], Var('fweet'))),
asset: Get(Select(['data', 'asset'], Var('fweet')))
},
// And now we return a nested doc
{
fweet: Var('fweet'),
author: Var('author'),
asset: Var('asset'),
}
)
)
)
當然.. 如果我們想要獲取的東西不是存儲的引用但我們想要加入一個屬性怎么辦? 那么想象一下,我們想要獲取一條推文上有多個評論? 這就是索引的用武之地!
Map(
Paginate(Documents(Collection('fweets'))),
Lambda('f',
Let({
fweet: Get(Var('f')),
author: Get(Select(['data', 'author'], Var('fweet'))),
asset: Get(Select(['data', 'asset'], Var('fweet'))),
comments: Map(
Paginate(Match(Index('comments_by_fweet_ordered'), Var('f'))),
Lambda(
// my index has two values, I only need the comment reference but adding the ts makes them appear in order!
['ts', 'commentref'],
Get(Var('commentref'))
)
)
},
// And now we return a nested doc
{
fweet: Var('fweet'),
author: Var('author'),
asset: Var('asset'),
comments: Var('comments')
}
)
)
)
就像那樣......你可以逐漸增加復雜性並進行非常復雜的查詢。 我的應用程序中的查詢繼續這樣,以獲取諸如推文統計信息之類的內容,甚至是原始推文(如果它是轉推)實際上在 FQL 中幾乎沒有您不能做的事情:)
所以首先,最好將 refs 存儲在文檔中而不是 ids 中。
在問題中存儲示例帖子時,它應該是這樣的(使用 JS 驅動程序):
{
title: 'Lorem ipsum',
authorRef: q.Ref(q.Collection("authors"), "1234556456858234")
}
然后,要獲得包含嵌套作者的帖子,您需要使用Let
創建自定義對象。
這將是這樣的(再次使用 JS 驅動程序):
q.Let(
{
postDoc: q.Get(q.Ref(Collection('posts'), '192903209792046592')),
authorRef: q.Select(['data', 'authorRef'], q.Var('postDoc')),
authorDoc: q.Get(q.Var('authorRef')),
},
{
title: q.Select(['data', 'title'], q.Var('postDoc')),
author: {
name: q.Select(['data', 'name'], q.Var('authorDoc')),
}
}
)
哪個會返回:
{
title: 'Lorem ipsum',
author: {
name: 'John Doe'
}
}
另一種選擇可能是簡單地並排返回兩個完整文檔:
q.Let(
{
postDoc: q.Get(q.Ref(Collection('posts'), '192903209792046592')),
authorRef: q.Select(['data', 'authorRef'], q.Var('postDoc'))
},
{
postDoc: q.Var('postDoc'),
authorDoc: q.Get(q.Var('authorRef')),
}
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.