Запрос Firestore для предметов с отметкой времени до сегодняшнего дня - PullRequest
0 голосов
/ 12 февраля 2019

В новом Cloud Firestore вы можете установить метку времени сервера для моего объекта сообщения, используя следующую строку при создании объекта:

showtime: firebase.firestore.FieldValue.serverTimestamp()

Это полезно для сообщений от любого пользователя, так как оно не полагаетсяу каждого пользователя локальные часы.

Проблема, с которой я сталкиваюсь, заключается в том, чтобы запросить и настроить поле showtime впоследствии.То, что я хочу сделать, это посмотреть любое сообщение, у которого есть время показа раньше, чем «сейчас».В моем приложении многие сообщения отодвинуты в будущее.Я хочу, чтобы только те, у кого есть расписание до сегодняшнего дня, были возвращены и отображены.

Вот мой запрос:

  var query = firebase.firestore()
                  .collection('messages')
                  .where('owner','==',userID)
                  .where('showtime','<',timenow)
                  .orderBy('showtime', 'desc')
                  .limit(25);

Проблема в том, что я не знаю, как получить текущее время(на сервере) для использования в запросе.В Firebase есть вызов now () для типа Timestamp, но я не уверен, как его назвать, и я не уверен, основываясь на некоторых других вопросах, совпадает ли метка времени Firebase с меткой времени Cloud Firestore!

Итаквопрос заключается в следующем: как установить переменную с именем timenow в текущее время на сервере и использовать ее в запросе для получения 25 сообщений до сих пор?(в Javascript на клиенте, а также в дополнительном указании для функции на сервере)

Итак, как быстро обновить метку времени показа на одну неделю позже, чем сейчас?

Надеюсь, у нас есть несколько Firebase / Cloud Firestore mavens на Stackoverflow!

** Выбор ответа ниже с предупреждением о запросе функции: вызов в Firebase к серверу для запроса текущей метки времени, чтобы код клиентаможет отработать одну стандартную часы.**

Ответы [ 3 ]

0 голосов
/ 27 февраля 2019

Продолжая превосходный ответ Алекса Данлопа, я оказался в похожей ситуации, и это имело смысл, когда я понял, что Firestore работает в соответствии с двумя принципами проектирования (или, по крайней мере, таков мой анализ)

  1. Акцент делается на простые запросы, которые передают вам живые обновления.Чтобы сделать это, запросы ограничены по сложности.Это берет на себя нагрузку на сервер базы данных Firestore и позволяет ему быстро (эффективно перезапускать) запросы.
    Из-за ограниченного языка запросов и нескольких операторов на стороне сервера (FieldValue - один из немногих), Googleможет безжалостно оптимизировать запросы.

  2. Есть много более сложных операций, которые требуются разработчикам.Вместо того, чтобы реализовывать их в Firestore, разработчикам предлагается ускорить облачную функцию, которая делает их ответственными (по коду и стоимости) за эту дополнительную сложность.

Если вы пришли из обычной БДВ дизайне, подобном Postgres, отсутствие выразительности запросов и операций на стороне сервера просто поражает.Если вы думаете о сценарии использования Firestore и его принципах, все это имеет смысл.

0 голосов
/ 01 марта 2019

Попробуйте правила безопасности Firestore с проверкой данных:

  match /messages/{msgId} {
    // optionally: request.time + someBuffer
    allow read: if request.time > resource.data.showtime;
  }

Я не думаю, что вы хотите доверять клиенту (поскольку вы упомянули, что хотите заблокировать доступ клиента к будущим сеансам).Помимо изменения их часов, они могли бы просто отредактировать javascript.

Возможно, потребуется буфер, чтобы не делать запрос недействительным, если есть некоторое расхождение между предоставленным клиентом Date.now() и правилами Firestore request.time, в частности, если request.time случается раньше, чем дата клиента, тогда запрос будет иметь документы, выходящие за пределы допустимого диапазона, и потерпит неудачу.

0 голосов
/ 18 февраля 2019

Вы правы serverTimestamp() именно для того, чтобы получить метку времени на сервере и не полагаться на локальные часы пользователей.Стоит отметить, что отправка сообщения и получение метки времени от локальных часов пользователей будут нормальными, поскольку метка времени сообщения не очень чувствительна ко времени.Конечно, вы хотели бы знать, когда сообщение отправлено, но если это в течение 1-2 секунд, это не проблема в большинстве случаев.

Если вы выполняете запрос на стороне клиента, ваш запрос не должен основываться на времени сервера, он должен основываться на стороне клиента.Так как это клиентский запрос, а не серверный запрос.

Вот клиентский запрос, который вам нужен.

const currentTime = new Date();
const query = firebase.firestore()
                  .collection('messages')
                  .where('owner','==',userID)
                  .where('showtime','<',currentTime)
                  .orderBy('showtime', 'desc')
                  .limit(25);

Этот запрос получит 25 сообщений с 'showtime' после текущеговремя на клиенте.

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

Вот как вы хотели бы, чтобы ваша облачная функция выглядела следующим образом:

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
admin.initializeApp()

exports.getUserMessages = functions.https.onCall((data, context) => {
    const uid = context.auth.uid;
    const firestore = admin.firestore();
    firestore.collection('messages')
             .where('owner', '==', uid)
             .where('showtime', '<', new Date())
             .orderBy('showtime', 'desc')
             .limit(25)
             .get()
             .then(snapshot => {
                return snapshot;
             });
});

Это дастсообщения, основанные на отметке времени сервера.Стоит отметить, что если вам не нужно быть очень чувствительным ко времени, это не очень хорошая идея.Поскольку этот вызов должен делать дополнительный ненужный вызов каждый раз, когда вы звоните.Потому что вы делаете вызов функции облака, а затем делаете запрос к базе данных firestore.Я бы порекомендовал вместо того, чтобы делать это на основе времени сервера, делать это на основе отметки времени клиента.В 99 раз из 100 разница во времени между клиентом и сервером не стоит дополнительных двойных вызовов, которые вы делаете, особенно когда вы думаете о масштабировании всего, когда набираете больше пользователей.

Надеюсь, что ответили на ваш вопрос :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...