Запрос с фильтрами диапазона и неравенства в обзоре нескольких полей

Cloud Firestore поддерживает использование фильтров диапазона и неравенства для нескольких полей в одном запросе. Теперь вы можете использовать условия диапазона и неравенства в нескольких полях и упростить разработку приложений, делегировав реализацию логики постфильтрации Cloud Firestore.

Фильтры диапазона и неравенства в нескольких полях

Следующий запрос возвращает всех пользователей, возраст которых превышает 35 лет, а рост составляет от 60 до 70 лет, используя фильтры диапазона по возрасту и росту.

Веб-версия 9 модульная

  const q = query(
      collection(db, "users"),
      where('age', '>', 35),
      where('height', '>', 60),
      where('height', '<', 70)
    );

Быстрый

 let query = db.collection("users")
   .whereField("age", isGreaterThan: 35)
   .whereField("height", isGreaterThan: 60)
   .whereField("height", isLessThan: 70)

Цель-C

 FIRQuery *query = 
  [[[[self.db collectionWithPath:@"users"]
 queryWhereField:@"age" isGreaterThan:@35]
    queryWhereField:@"height" isGreaterThan:@60] 
        queryWhereField:@"height" isLessThan:@70];

Ява Андроид

 Query query = db.collection("users")
  .whereGreaterThan("age", 35)
  .whereGreaterThan("height", 60)
  .whereLessThan("height", 70);

Котлин+KTX Android

 val query = db.collection("users")
  .whereGreaterThan("age", 35)
  .whereGreaterThan("height", 60)
  .whereLessThan("height", 70)

Джава

  db.collection("users")
    .whereGreaterThan("age", 35)
    .whereGreaterThan("height", 60)
    .whereLessThan("height", 70);

Node.js

db.collection("users")
  .where('age', '>', 35),
  .where('height', '>', 60),
  .where('height', '<', 70)

Рекомендации по индексированию

Прежде чем приступить к выполнению запросов, убедитесь, что вы прочитали о запросах и модели данных 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 и выглядеть следующим образом:

Джава

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");

Питон

db.collection("employees")
  .where("salary", ">", 100000)
  .where("experience", ">", 0)
  .order_by("salary")
  .order_by("experience");

Рекомендации по оптимизации индексов

При оптимизации индексов обратите внимание на следующие рекомендации.

Упорядочите поля индекса по равенствам, за которыми следует наиболее избирательный диапазон или поле неравенства.

Cloud Firestore использует крайние левые поля составного индекса для удовлетворения ограничений равенства и ограничения диапазона или неравенства, если таковые имеются, в первом поле запроса orderBy() . Эти ограничения могут уменьшить количество записей индекса, сканируемых Cloud Firestore. Cloud Firestore использует оставшиеся поля индекса для удовлетворения других ограничений диапазона или неравенства запроса. Эти ограничения не уменьшают количество записей индекса, которые сканирует Cloud Firestore, но отфильтровывают несовпадающие документы, чтобы уменьшить количество документов, возвращаемых клиентам.

Дополнительные сведения о создании эффективных индексов см. в определении идеального индекса .

Упорядочите поля в порядке убывания избирательности ограничений запроса.

Чтобы убедиться, что Cloud Firestore выберет оптимальный индекс для вашего запроса, укажите предложение orderBy() , которое упорядочивает поля в порядке убывания избирательности ограничений запроса. Более высокая избирательность соответствует меньшему подмножеству документов, тогда как более низкая избирательность соответствует большему подмножеству документов. Убедитесь, что вы выбрали поля диапазона или неравенства с более высокой избирательностью раньше при упорядочивании индекса, чем поля с более низкой избирательностью.

Чтобы свести к минимуму количество документов, которые Cloud Firestore сканирует и возвращает по сети, всегда следует упорядочивать поля в порядке убывания избирательности ограничений запроса. Если набор результатов не находится в требуемом порядке и ожидается, что набор результатов будет небольшим, вы можете реализовать логику на стороне клиента, чтобы изменить его порядок в соответствии с вашими ожиданиями.

Например, предположим, что вы хотите выполнить поиск по коллекции сотрудников, чтобы найти сотрудников, чья зарплата превышает 100 000, и упорядочить результаты по году опыта сотрудника. Если вы ожидаете, что только небольшое количество сотрудников будет иметь зарплату более 100 000, то наиболее эффективный способ написать запрос будет следующим:

Джава

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`

Питон

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 все равно читаются, что увеличивает задержку и стоимость запроса.

Цены

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

Подробную информацию смотрите на странице Цены .

Ограничения

Помимо ограничений запроса , обратите внимание на следующие ограничения перед использованием запросов с фильтрами диапазона и неравенства для нескольких полей:

  • Запросы с фильтрами диапазона или неравенства в полях документа и только ограничениями равенства для ключа документа (__name__) не поддерживаются.
  • Cloud Firestore ограничивает количество полей диапазона или неравенства до 10. Это сделано для того, чтобы запросы не становились слишком дорогими для выполнения.

Что дальше