Запрос диапазона дат Firebase для выборки документов, имеющих starDate и endDate - PullRequest
1 голос
/ 29 апреля 2019

У меня есть коллекция задач в моей базе данных Firestore, например:

"tasks": {
    v8NC4GovVOPe21fhwtp0 : {
        id: "v8NC4GovVOPe21fhwtp0"
        status: 0
        dateFrom: 30 april 2019 at 00:00:00 UTC-3
        dateTo: 05 may 2019 at 00:00:00 UTC-3
        ....
    },
    v7NC4GaxVOPe48ftstp1 : {
        id:"v7NC4GaxVOPe48ftstp1"
        status: 0
        dateFrom: 29 april 2019 at 00:00:00 UTC-3
        dateTo: 02 may 2019 at 00:00:00 UTC-3
        ....
    }
}

В документе есть поле dateFrom, которое указывает первую дату, когда пользователь может начать работу над этой задачей, и поле dateTo, которое указывает последний день, когда пользователь должен завершить эту задачу.

Я пытался получить все задания с апреля 2019 года, то есть те, которые dateFrom или dateTo принадлежат этому месяцу / году (в этом примере, если месяц апрель-2019, он должен получить оба задачи).

В Android я получаю первую дату выбранного месяца (startDate) и последнюю дату из выбранного месяца (endDate), и я пытался сделать что-то вроде:

val missionsCollection = FirebaseFirestore.getInstance()
        .collection("/users").document(uid).collection("tasks")
        .whereGreaterThanOrEqualTo("dateFrom", startDate).whereLessThanOrEqualTo("dateTo", endDate)

Но я получаю сообщение о том, что All where filters other than whereEqualTo() must be on the same field. But you have filters on 'dateFrom' and 'dateTo'.

Я думал о некоторых обходных путях, но все они выглядят плохо, и хотя я не мог найти хорошее решение, я уверен, что должно быть одно.

1 Ответ

1 голос
/ 30 апреля 2019

Firestore позволяет объединить несколько методов where () для создания более специфических запросов, но только для одного и того же поля. Как вы, вероятно, можете видеть в официальной документации относительно Ограничения запроса :

Cloud Firestore не поддерживает следующие типы запросов:

  • Запросы с фильтрами диапазона в различных полях, как описано в предыдущем разделе.

Так что фильтры диапазона на разных полях запрещены.

Чтобы достичь того, что вы хотите, вам нужно дважды запросить базу данных, один раз, чтобы сопоставить данные с помощью вызова:

.whereGreaterThanOrEqualTo("dateFrom", startDate)

А во-вторых, используя вызов:

.whereLessThanOrEqualTo("dateTo", endDate)

Но, к сожалению, вы не можете использовать их в одном запросе.

Изменить:

Когда мы разрабатываем схему базы данных, в основном мы структурируем ее для наших запросов. Таким образом, помимо вышеупомянутого решения, в котором вы можете фильтровать одно поле в запросе и другое поле в коде на стороне клиента, существует также другой подход, в котором вы можете объединить значения двух диапазонов в одно поле в каким-то образом, который позволит использовать ваш вариант с одним полем.

Один из самых удачных примеров, которые я видел до сих пор, - это комбинация, используемая в Geohashes для фильтрации по широте и долготе, как объяснил Фрэнк ван Пуффелен в следующем видео:

Зная разницу в усилиях между этими двумя решениями, я бы порекомендовал использовать первое.

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

 db.collection("tasks-aps-mar")
    .whereGreaterThanOrEqualTo("day", 1)
    .whereLessThanOrEqualTo("day", 30);

Еще более общим решением было бы сохранить задачи в коллекции для каждого месяца, а затем выполнить запрос, чтобы получить все задачи, соответствующие желаемому месяцу. В вашем случае вы должны запросить базу данных, чтобы получить документы в одной из каждой коллекции tasks-mar-2019, tasks-apr-2019, tasks-may-2019 и т. Д.

Что касается вашего комментария, использование массивов вам совсем не поможет, поскольку вы не можете использовать интервалы диапазона.

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