Порядок запросов Firestore в поле с фильтром в другом поле

У меня проблема с условием запроса в Google Cloud Firestore.

Любой может мне помочь.

Порядок запросов Firestore в поле с фильтром в другом поле

Ниже приведен мой код, чтобы первый документ начинался с HA_ и упорядочивался по ID DESC.

public Article getLastArticleProvider() {
    ApiFuture<QuerySnapshot> query = firebaseDB.getTblArticles()
            .whereGreaterThanOrEqualTo("articleId", "HA_")
            .orderBy("id", Query.Direction.DESCENDING)
            .limit(1)
            .get();

    QuerySnapshot snapshotApiFuture;
    Article article = null;

    try {
        snapshotApiFuture = query.get();
        List<QueryDocumentSnapshot> documents = snapshotApiFuture.getDocuments();
        for (QueryDocumentSnapshot document : documents) {
            article = document.toObject(Article.class);
        }
    } catch (InterruptedException | ExecutionException e) {
        return null;
    }
    return article;
}

Я хочу получить последний идентификатор статьи, где articleId начинается с «HA_» или «XE_».

Пример для изображения выше:

  • if (articleId начинается с "HA_") => возвращает объект с идентификатором 831
  • if (articleId начинается с "XE_") => возвращает объект с идентификатором 833

Теперь я получаю сообщение об ошибке

java.util.concurrent.ExecutionException: com.google.api.gax.rpc.InvalidArgumentException: io.grpc.StatusRuntimeException: INVALID_ARGUMENT: inequality filter property and first sort order must be the same: articleId and id

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
6
0
5 127
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Как говорит следующая ошибка:

inequality filter property and first sort order must be the same: articleId and id

Таким образом, вы не можете фильтровать свои элементы и сортировать их одновременно, используя разные свойства, в вашем случае articleId и id.

Так же есть пример как нет сделать это в официальная документация:

  • Фильтр диапазона и первый порядок по разным полям

     citiesRef.whereGreaterThan("population", 100000).orderBy("country"); //Invalid
    

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

У вас есть предложения?

LongLv 24.02.2019 11:31

Я не уверен, что понимаю ваш вопрос. Предлагается не фильтровать и упорядочивать одно и то же свойство, потому что это невозможно, верно?

Alex Mamo 24.02.2019 11:40

Извините за мой английский, но мне нужен результат, похожий на запрос sql: выберите * из статей, где articleId LIKE '%HA_%' упорядочить по идентификатору DESC limit 1

LongLv 24.02.2019 11:52

К сожалению, в путях Firestore к документам нет подстановочных знаков. Так что такого запроса не существует. Единственный вариант, который у вас есть, — использовать методы whereGreatedThan и whereLessThan.

Alex Mamo 25.02.2019 09:12

TL;DR

Добавьте фиктивный порядок сразу после свойства фильтра неравенства и измените приоритет запроса в соответствии с вашими желаниями.

Я столкнулся с той же проблемой в javascript, но я считаю, что это также решение для java.

Полное решение:

Когда я запускаю свой запрос:

module.exports.getLastGroupChat = async function (groupId) {
    let colRef = db.collection('messages')
    colRef = colRef.where('groupId', '==', groupId)
    colRef = colRef.where('userId', '!=', '')
    colRef = colRef.orderBy('timestamp', 'desc').limit(1)
    const doc = await colRef.get()
    return doc

}

И получил:

inequality filter property and first sort order must be the same: userId and timestamp

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

Кроме того, мне пришлось изменить приоритет запроса, чтобы добиться фиктивного порядка сортировки свойства неравенства.

Примечание: Вы можете запустить where -> order -> where -> order по тому же запросу!

module.exports.getLastGroupChat = async function (groupId) {
    let colRef = db.collection('messages')
    colRef = colRef.where('userId', '!=', '')
    colRef = colRef.orderBy('userId', 'desc')
    colRef = colRef.where('groupId', '==', groupId)
    colRef = colRef.orderBy('timestamp', 'desc').limit(1)
    const doc = await colRef.get()
    return doc
}

Этот запрос отлично работал в моем локальном хранилище отладки. Внесите изменения в облачные функции Firebase и активируйте свою функцию. Проверьте свои журналы функций, вы можете получить ошибку индексации.

The query requires an index. You can create it here: https://console.firebase.google.com/v1/r/project...

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

Развлекайся! :)

Я попробовал ваше решение на Android, но двойное предложение where с разными полями не работает. Вы можете проверить это снова? Я думаю, что это сработало в вашем случае, потому что вы используете оператор "= = ". Ошибка: все, где фильтры с неравенством (notEqualTo, notIn, lessThan, lessThanOrEqualTo, GreatThan или GreatThanOrEqualTo) должны быть в одном поле. .whereGreaterThanOrEqualTo("current_date", timestamp) .orderBy("current_date", Query.Direction.DESCENDING) .whereNotEqualTo(country, 0) .orderBy(country)

Raghav Satyadev 13.04.2021 09:51

Есть несколько (но важных) ограничений запросов firestore. Вы можете увидеть их все в следующей документации firebase.google.com/docs/firestore/query-data/queries. Используйте это в любое время, когда вы сталкиваетесь со сложными запросами.

genericUser 13.04.2021 11:50

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

genericUser 13.04.2021 11:56

Я только что прочитал это вчера, теперь, к сожалению, возвращаюсь к MySQL.

Raghav Satyadev 15.04.2021 10:14

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

genericUser 15.04.2021 12:18

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

Ответ заключается в том, что вы МОЖЕТЕ выполнять фильтрацию и сортировку по разным полям.

вы можете связать порядок и фильтры, однако, если вы сначала фильтруете, вам нужно упорядочить по этому фильтру, прежде чем вы сможете упорядочить по любому другому полю. например

citiesRef.where('population', '>', 2500000).orderBy('population').orderBy('country');

Это в их документах. https://firebase.google.com/docs/firestore/query-data/order-limit-data#order_and_limit_data

However, if you have a filter with a range comparison (<, <=, >, >=), your first ordering must be on the same field, see the list of orderBy() limitations below.

вы можете связать orderBys разных полей, я только что сделал это по одному из своих запросов. (вы можете получить сообщение об ошибке при первом запуске, оно просит вас создать индекс, у него даже есть ссылка для создания индекса)

await db.collection('daily_equipments').where('date', '<', tomorrow._d).where('date', '>=', date).orderBy('date').orderBy('order','asc').get();

Другие вопросы по теме