Как реализовать getOrCreate в транзакции Firestore? - PullRequest
0 голосов
/ 22 мая 2018

Я пытаюсь реализовать сервис закладок для цитат.

  • Для данной коллекции цитат в ней есть четыре инфо-цитаты, userId, authorId и sourceId.
  • Для автораколлекция, у нее есть два инфо-имени, userId
  • Для исходной коллекции у него есть три инфо-имени (Star Wars), тип (книга, фильм), userId

Когдапользователь пытается сохранить цитату, я хотел бы иметь транзакцию, где я проверю, существует ли автор (запрос по имени. если да, верните authorId. если нет, создайте автора).То же самое касается источника + типа.И автор, и источник вернут свои идентификаторы.Во время сохранения цитаты объект цитаты будет создан с authorId и sourceId .

Возможен ли такой случай?Я проверил, что в транзакции Firestore.firestore (). Есть только функция getDocument, и я не могу выполнить запрос с помощью whereField ().

Я где-то читал, что мы можем принудительно применитьсоздать с помощью правил и выдать ошибку или что-то еще в try / catch, где блок catch выполнит getDocument?

В случае, когда я не могу выполнить запрос внутри транзакции и могу толькополагаться на getDocument, означает ли это, что идентификатор коллекции автора / источника должен быть составным ключом типа «userId + hash (имя автора / источника)»? *

Какой совет по выполнению такого действия?Или Firestore не может обработать такой вариант использования?

В общем, я пытаюсь сделать это (в псевдокоде) ...

Firestore.transaction {

  // Get or create author
  let author = Author.getOrCreate("Yoda", userId)

  // Get or create source
  let source = Source.getOrCreate("Star Wars", "film", userId)

  // Save quote
  let quote = Quote.create({
     quote: "Do or do not. There is no try", 
     authorId: author.id, 
     sourceId: source.id, 
     userId: userId
  })

}

1 Ответ

0 голосов
/ 23 мая 2018

В транзакции все чтения должны идти первыми.Вы можете использовать transaction.getAll(), чтобы получить автора и источник, а затем создать их, если они не существуют:

const authorsRef = db.collection('authors')
const sourcesRef = db.collection('sources')
const quotesRef = db.collection('quotes')

db.runTransaction(transaction => transaction
  .getAll(
    authorsRef.where('name', '==', 'Yoda').get(),
    sourcesRef.where('name', '==', 'Star Wars').where('type', '==', 'film').get()
  )
  .then(([ authorDoc, sourceDoc ]) => {
    let author = authorDoc
    let source = sourceDoc


    if (!author.exists) {
      author = authorsRef.doc()
      transaction.set(author, { /* add author fields here */ })
    }

    if (!source.exists) {
      source = sourcesRef.doc()
      transaction.set(source, { /* add source fields here */ })
    }

    transaction.set(quotesRef.doc(), {
      // add other quote fields here
      authorId: author.id,
      sourceId: source.id
    })
  })
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...