Cloud Firestore поддерживает использование фильтров диапазона и неравенства для нескольких полей в одном запросе. Вы можете задавать условия диапазона и неравенства для нескольких полей и упростить разработку приложения, делегировав реализацию логики постфильтрации Cloud Firestore.
Фильтры диапазонов и неравенств по нескольким полям
В следующем запросе используются фильтры диапазона по численности и плотности населения,чтобы получить все города,в которых численность населения превышает 1 000 000 человек,а плотность населения составляет менее 10 000 человек на единицу площади.
Веб-версия 9 (модульный)
const q = query(
collection(db, "cities"),
where('population', '>', 1000000),
where('density', '<', 10000),
);
Swift
let query = db.collection("cities")
.whereField("population", isGreaterThan: 1000000)
.whereField("density", isLessThan: 10000)
Objective-C
FIRQuery *query =
[[[[self.db collectionWithPath:@"cities"]
queryWhereField:@"population" isGreaterThan:@1000000]
queryWhereField:@"density" isLessThan:@10000];
Java Android
Query query = db.collection("cities")
.whereGreaterThan("population", 1000000)
.whereLessThan("density", 10000);
Kotlin+KTX Android
val query = db.collection("cities")
.whereGreaterThan("population", 1000000)
.whereLessThan("density", 10000)
Проложить маршрут
query := client.Collection("cities").
Where("population", ">", 1000000).
Where("density", "<", 10000)
Java
db.collection("cities")
.whereGreaterThan("population", 1000000)
.whereLessThan("density", 10000);
Node.js
db.collection("cities")
.where('population', '>', 1000000),
.where('density', '<', 10000)
Python
from google.cloud import firestore
db = firestore.Client()
query = db.collection("cities")
.where("population", ">", 1000000)
.where("density", "<", 10000)
PHP
C#
Ruby
query = cities_ref.where("population", ">", "1000000")
.where("density", "<", 10000)
C++
CollectionReference cities_ref = db->Collection("cities");
Query query = cities_ref.WhereGreaterThan("population", FieldValue::Integer(1000000))
.WhereLessThan("density", FieldValue::Integer(10000));
Unity
CollectionReference citiesRef = db.Collection("cities");
Query query = citiesRef.WhereGreaterThan("population", 1000000)
.WhereLessThan("density", 10000);
Dart
final citiesRef = FirebaseFirestore.instance.collection('cities')
final query = citiesRef.where("population", isGreaterThan: 1000000)
.where("density", isLessThan: 10000);
Особенности индексирования
Прежде чем выполнять запросы, ознакомьтесь с информацией о [запросах][1] и [модели данных][2] Cloud Firestore.
В Cloud Firestore условие ORDER BY запроса определяет, какие индексы можно использовать для его обработки. Например, для запроса ORDER BY a ASC, b ASC требуется составной индекс для полей a ASC, b ASC.
Чтобы оптимизировать производительность и стоимость запросов Cloud Firestore, оптимизируйте порядок полей в индексе. Для этого убедитесь, что индекс упорядочен слева направо, чтобы запрос сводился к набору данных, который предотвращает сканирование ненужных записей в индексе.
Предположим, вы хотите выполнить поиск по коллекции сотрудников и найти сотрудников из США, чья зарплата превышает 100 000 долларов США, а стаж работы превышает 0 лет. Основываясь на вашем понимании набора данных, вы знаете, что ограничение по зарплате является более избирательным, чем ограничение по опыту. Идеальным индексом, который уменьшит количество сканирований, будет (salary [...], experience [...]). Таким образом, быстрый и экономичный запрос будет содержать salary перед experience и выглядеть следующим образом:
Java
db.collection("employees")
.whereGreaterThan("salary", 100000)
.whereGreaterThan("experience", 0)
.orderBy("salary")
.orderBy("experience");
Node.js
db.collection("employees")
.where("salary", ">", 100000)
.where("experience", ">", 0)
.orderBy("salary")
.orderBy("experience");
Python
db.collection("employees")
.where("salary", ">", 100000)
.where("experience", ">", 0)
.order_by("salary")
.order_by("experience");
Рекомендации по оптимизации индексов
При оптимизации индексов учитывайте следующие рекомендации.
Упорядочивайте поля индекса по равенствам, а затем по наиболее избирательному диапазону или полю неравенства.
Cloud Firestore использует крайние левые поля составного индекса, чтобы удовлетворить ограничения равенства и диапазона или неравенства (если есть) в первом поле запроса orderBy(). Эти ограничения могут уменьшить количество записей в индексе, которые сканирует Cloud Firestore. Cloud Firestore использует оставшиеся поля индекса, чтобы удовлетворить другие ограничения диапазона или неравенства запроса. Эти ограничения не уменьшают количество записей в индексе, которые сканирует Cloud Firestore, но отфильтровывают несоответствующие документы, чтобы уменьшить количество документов, возвращаемых клиентам.
Дополнительную информацию о создании эффективных индексов можно найти в разделе [Свойства индекса][4].
Упорядочивайте поля по убыванию избирательности ограничений запроса.
Чтобы Cloud Firestore выбрал оптимальный индекс для вашего запроса, укажите предложение orderBy(), которое упорядочивает поля в порядке убывания избирательности ограничений запроса. Чем выше избирательность, тем меньше документов будет соответствовать запросу, и наоборот. Убедитесь, что вы выбираете поля диапазона или неравенства с более высокой селективностью раньше в порядке индекса, чем поля с более низкой селективностью.
Чтобы минимизировать количество документов, которые Cloud Firestore сканирует и возвращает по сети, всегда упорядочивайте поля в порядке убывания избирательности ограничений запроса. Если набор результатов не упорядочен нужным образом и ожидается, что он будет небольшим, вы можете реализовать клиентскую логику, чтобы упорядочить его в соответствии с вашими ожиданиями.
Например, предположим, что вы хотите выполнить поиск по коллекции сотрудников, чтобы найти сотрудников из США, чья зарплата превышает 100 000 долларов США, и упорядочить результаты по году опыта работы сотрудника. Если вы ожидаете,что только у небольшого числа сотрудников зарплата будет превышать 100 000 долларов, то наиболее эффективный способ написать запрос будет следующим:
Java
db.collection("employees")
.whereGreaterThan("salary", 100000)
.orderBy("salary")
.get()
.addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
@Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
// Order results by `experience`
}
});;
Node.js
const querySnapshot = await db.collection('employees')
.where("salary", ">", 100000)
.orderBy("salary")
.get();
// Order results by `experience`
Python
results = db.collection("employees")
.where("salary", ">", 100000)
.order_by("salary")
.stream()
// Order results by `experience`
Если добавить в запрос сортировку по полю experience, будет получен тот же набор документов и не потребуется сортировать результаты на клиентах, но запрос может прочитать гораздо больше посторонних записей в индексе, чем предыдущий. Это связано с тем, что Cloud Firestore всегда предпочитает индекс, поля которого соответствуют предложению order by запроса. Если в предложение order by добавить experience, то Cloud Firestore выберет индекс (experience [...], salary [...]) для вычисления результатов запроса. Поскольку других ограничений для experience нет, Cloud Firestore прочитает все записи в индексе коллекции employees, прежде чем применить фильтр salary, чтобы найти окончательный набор результатов. Это означает, что записи в индексе, которые не соответствуют фильтру salary, все равно считываются, что увеличивает задержку и стоимость запроса.
Цены
Запросы с фильтрами по диапазону и неравенству в нескольких полях оплачиваются на основе прочитанных документов и записей в индексе.
Подробную информацию можно найти на странице [Цены][5].
Ограничения
Помимо [ограничений на запросы][6], перед использованием запросов с фильтрами по диапазону и неравенству в нескольких полях обратите внимание на следующие ограничения:
- Запросы с фильтрами диапазона или неравенства в полях документа и только ограничениями равенства в ключе документа
(__name__)не поддерживаются. - В Cloud Firestore количество полей с диапазонами или неравенствами ограничено 10. Это позволяет избежать слишком высоких расходов на выполнение запросов.
Дальнейшие действия
- Подробнее [об оптимизации запросов][3]…
- Подробнее [о выполнении простых и составных запросов][8]…
- Узнайте, [как Cloud Firestore использует индексы][9].
[1]: /docs/firestore/query-data/get-data [2]: /docs/firestore/data-model [3]: /docs/firestore/query-data/multiple-range-optimize-indexes [4]: /docs/firestore/concepts/index-overview#index_properties [5]: /docs/firestore/pricing [6]: /docs/firestore/query-data/queries#query_limitations [7]: https://en.wikipedia.org/wiki/Disjunctive_normal_form [8]: /docs/firestore/query-data/queries [9]: /docs/firestore/concepts/index-overview [10]: /docs/firestore/query-data/multiple-range-optimize-indexes