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] и Cloud Firestore [модели данных][2].
В 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