Как получить вложенные документы в FaunaDB? - PullRequest
1 голос
/ 08 апреля 2020

Чтобы получить один документ в Фауне, мы делаем:

q.Get(q.Ref(q.Collection('posts'), '192903209792046592'))

И мы получаем что-то вроде:

{
  data: {
    title: 'Lorem ipsum',
    authorId: '892943607792046595'
  }
}

Можно ли вместо этого получить пост и автора в тот же запрос?

Примерно так:

{
  data: {
    title: 'Lorem ipsum',
    author: {
      name: 'John Doe'
    }
  }
}

Ответы [ 2 ]

2 голосов
/ 09 апреля 2020

Так как это общий вопрос, я собираюсь его расширить и дать вам всю информацию, которая необходима для начала работы. Недавно я написал пример, который вскоре также проиллюстрирует это подробно.

Я собираюсь создать шаг за шагом, чтобы быть как можно более образованным. Скажем так: мы пишем приложение, подобное твиттеру, и хотим получать твиты. Первое, что мы сделаем, это просто получим список твитов.

Прежде всего .. Получение ссылок

Paginate(Documents(Collection('fweets')))

, которое возвращает список ссылок

... или значения индекса

Paginate(Documents(Index('some_index')))

, которые возвращает все значения, которые вы выбрали при создании индекса, что-то вроде: [[value1, value2], ...]

Это вернет страницу ссылок или, по сути, список ссылок.

Получение фактических документов списка с помощью Get

Затем вы делаете то, что сделали в своем вопросе, вы Получаете ссылку, сопоставляя ее с Map (и Map будет вашей рабочей лошадкой для ответа на ваш вопрос, когда мы go будем дальше)

Map(
   Paginate(Documents(Collection('fweets'))),
   Lambda('ref', Var('ref'))
)

Преобразование этих документов для получения других данных (ваш конкретный c вопрос)

Вы можете использовать ту же технику, что и мы, чтобы получить ссылки, нанести на карту документ. Только сейчас мы можем получить ссылки на другие коллекции. Представьте, что у меня есть Автор в каждом из моих Твитов , давайте получим этого автора. Мы собираемся использовать пользователя 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:)

0 голосов
/ 08 апреля 2020

Итак, во-первых, лучше хранить ссылки в документах, а не в идентификаторах.

При сохранении примера сообщения в вопросе это должно выглядеть примерно так (с драйвером JS):

{
  title: 'Lorem ipsum',
  authorRef: q.Ref(q.Collection("authors"), "1234556456858234")
}

Затем, чтобы получить сообщение с вложенным автором, вам нужно создать пользовательские объекты с Let.

Это было бы что-то вроде (снова с драйвером JS):

q.Let(
  {
    postInstance: q.Get(q.Ref(Collection('posts'), '192903209792046592'))
  },
  {
    title: q.Select(['data', 'title'], q.Var('postInstance')),
    author: q.Let(
      {
        authorInstance: q.Get(q.Ref(q.Collection('authors'), q.Select(['data', 'authorRef', 'id'], q.Var('postInstance'))))
      },
      {
        name: q.Select(['data', 'name'], q.Var('authorInstance')))
      }
    )
  }
)

Что бы вернуть:

{
  title: 'Lorem ipsum',
  author: {
    name: 'John Doe'
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...