Я использую Firestore и запрашиваю данные с orderBy
, установленным на updatedAt
в descending
порядке, и ограничиваю результаты до 2 элементов на странице (в целях тестирования). Однако я сталкиваюсь с неожиданным поведением при обновлении данных.
Когда я обновляю самый старый элемент на второй странице, чтобы он имел последнюю метку времени updateAt, он перемещается на первую позицию на первой странице, фактически удаляя его со второй страницы. Кроме того, второй элемент на первой странице также удаляется.
Вот расшифровка ситуации:
Начальное состояние:
Page 1: ['item1', 'item2'] (no `startAfter` specified)
Page 2: ['item3', 'item4'] (starting after 'item2')
После обновления элемента 4 (updatedAt изменен на последний):
Page 1: ['item4', 'item1']
Page 2: ['item3']
Однако мой ожидаемый результат:
Page 1: ['item4', 'item1']
Page 2: ['item2', 'item3']
// Query example
const query = firestore.collection('myCollection')
.where('tests', 'array-contains', `test`)
.orderBy('updatedAt', 'desc')
.limit(2)
.startAfter(startAfterVar)
.onSnapshot(snapshot => {
// Do something to store
});
Мы очень ценим вашу помощь в решении этой проблемы. Спасибо!
Обновлено 1:
Вопрос: То есть вы фактически утверждаете, что элемент2 удален из базы данных? Или просто не отображается?
О: По сути, item2 не отображается и не удаляется из БД.
Вопрос: Можете ли вы отредактировать свой вопрос и добавить структуру базы данных в виде снимка экрана?
А: Структура данных:
myCollection (collection)
|
--- item1 (document)
|
--- tests: [array string]
--- updatedAt: [timestamp]
--- otherFields: ...
Обновлено 2:
Я реализую бесконечную нумерацию страниц в своем запросе
Обновление 3:
Обновлен скриншот коллекции тем.
Мой фактический запрос
// Query example
const query = firestore.collection('topics')
.where('members', 'array-contains', userID)
.orderBy('lastLoggedAt', 'desc')
.limit(2)
.startAfter(startAfterVar)
.onSnapshot(snapshot => {
// Do something to store
});
Привет @Alex Mamo, я только что обновил свой вопрос в Обновлении 1, этого достаточно? Спасибо :bow:
@Алекс Мамо Извините, но, похоже, произошло недоразумение. В настоящее время я использую Firestore, а не базу данных Realtime. В Firestore нет экспорта JSON как базы данных реального времени.
Извини за это. Вместо описания того, как выглядит ваша база данных, отредактируйте свой вопрос и добавьте его снимок экрана.
@AlexMamo Спасибо за ваш ответ. Я обновил скриншот документа в обновлении 3.
Привет @BrianBurton, я ценю твой ответ. Вы предполагаете, что достаточно указать номер страницы для параметра startAt, а не передавать последний снимок из предыдущего запроса? У меня сложилось впечатление, что startAt также будет частью результирующего набора. Не могли бы вы подробно описать свое решение в ответе? Я пробую ваше предложение.
Нет, извини, я ошибся. Я опубликовал ответ, который должен решить вашу проблему. Решение состоит в том, чтобы использовать startAt(), но я забыл, что вы не можете передавать индекс.
Отказ от ответственности: нумерация страниц с прослушивателями в реальном времени сложна.
То, что вы описываете, является ожидаемым поведением. Начиная с этого набора данных:
[item1, item2, item3, item4]
Когда вы настраиваете первый прослушиватель, вы читаете два документа для item1
и item2
. Затем вы создаете второй прослушиватель, который начинается после item2
, и затем он читает item3
и item4
.
Теперь измените item4
, чтобы стать первым в порядке сортировки. Итак, получается:
[item4, item1, item2, item3]
Итак, первый слушатель теперь видит item4
и item1
. Но второй прослушиватель по-прежнему запускается после item2
, поэтому он видит только item3
, а вы эффективно скрываете item2
.
Поскольку перемещение элемента меняет курсор всех страниц после него, вам потребуется повторно привязать всех слушателей к их новым документам курсора. Поэтому вам нужно будет отсоединить всех прослушивателей и воссоздать их или создать дополнительные прослушиватели для документов, которые находятся между существующими прослушивателями.
Именно поэтому библиотека FirebaseUI поддерживает только разбиение на страницы без прослушивателей в реальном времени: разбиение на страницы с обновлениями данных в реальном времени затруднено.
Привет @Frank, спасибо за твое предложение. Конечно, нет другого выхода, кроме как повторно обновить всех слушателей новым якорем для нумерации страниц в реальном времени.
Если я правильно понимаю ваш вопрос, проблема в использовании startAfter()
, которое исключает указанный документ из результатов.
В документации говорится:
Используйте методы startAt() или startAfter(), чтобы определить начальную точку запроса. Метод startAt() включает начальную точку, а метод startAfter() исключает ее. Например, если вы используете startAt(A) в запросе, он возвращает весь алфавит. Если вместо этого вы используете startAfter(A), он возвращает B-Z.
Если вы измените startAfter()
на startAt()
, он должен вернуть элемент2.
// Query example
const query = firestore.collection('topics')
.where('members', 'array-contains', userID)
.orderBy('lastLoggedAt', 'desc')
.limit(2)
.startAt(startAfterVar)
.onSnapshot(snapshot => {
// Do something to store
});
Привет @ Брайан, спасибо за ответ. Извините, но кажется странным, что при использовании startAt вместо startAfter страница 2 включает [item2, item3] после того, как страница 1 содержала [item1, item2]
Если вы используете startAt, вы должны использовать startAt(item3) для страницы 2.
Я думаю, мне также нужно повторно привязать прослушиватель, если элемент 3 был перенесен на первую страницу, это то же самое, что и в случае startAfter.
То есть вы по сути утверждаете, что
item2
удален из базы данных? Или просто не отображается? Можете ли вы отредактировать свой вопрос и добавить структуру базы данных в виде снимка экрана?