Firestore: как выполнить запрос с неравенством / не равно

Я хочу выбрать из коллекции Firestore только статьи, написанные НЕ мной.
Неужели это так сложно?

У каждой статьи есть поле owner_uid.

Вот и все:
Я ПРОСТО хочу написать эквивалент "select * from articles where uid<>request.auth.uid"

TL; DR: решение уже найдено: использование для языков / платформ: https://firebase.google.com/docs/firestore/query-data/queries#kotlin+ktx_5


person android51130    schedule 12.11.2017    source источник
comment
Firestore теперь поддерживает оператор where in. Проверить мой ответ и обновить принятый ответ   -  person TSR    schedule 13.09.2020


Ответы (8)


ИЗМЕНИТЬ 18 сентября 2020 г.

В примечаниях к выпуску Firebase говорится, что теперь есть not-in и != запросы. (Теперь доступна соответствующая документация.)

  • not-in находит документы, в которых значение указанного поля отсутствует в указанном массиве.
  • != находит документы, в которых значение указанного поля не совпадает с указанным значением.

Ни один из операторов запроса не будет соответствовать документам, в которых отсутствует указанное поле. Обязательно ознакомьтесь с документацией по синтаксису для вашего языка.

ОРИГИНАЛЬНЫЙ ОТВЕТ

Firestore не предоставляет проверки на неравенство. Согласно документации:

Метод where () принимает три параметра: поле для фильтрации, операцию сравнения и значение. Сравнение может быть ‹,‹ =, ==, ›или› =.

Операции неравенства не масштабируются, как другие операции, использующие index. Индексы Firestore подходят для запросов диапазона. С этим типом индекса для запроса неравенства серверной части все равно придется сканировать каждый документ в коллекции, чтобы получить результаты, а это очень плохо для производительности, когда количество документов растет.

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

У вас также есть возможность использовать несколько запросов, чтобы исключить отдельное значение. Примерно так, если вы хотите все, кроме 12. Запросите значение ‹12, затем запросите значение› 12, а затем объедините результаты в клиенте.

person Doug Stevenson    schedule 12.11.2017
comment
локально но как? Если в сборнике я прочитал 10 тысяч статей, это означает, что мне нужно безумно много раз запрашивать этот сборник с разбивкой на страницы, прежде чем я дойду до непрочитанных статей. - person android51130; 12.11.2017
comment
‹Br› например, как получить только статьи, которые я НЕ ЧИТАЮ? ‹Br› сохранение readed_article_ids в моем пользовательском документе Firestore Document увеличит мой пользовательский документ, и каждый документ firestore имеет ограничение в 1 МБ - когда-нибудь массив readed_article_ids в моем пользовательском документе будет превышайте этот порог. ‹br› Так запутались: ((( - person android51130; 12.11.2017
comment
Если у вас есть более конкретный вопрос о моделировании данных, это звучит как другой вопрос. - person Doug Stevenson; 12.11.2017
comment
хм, мне нужно создать новый вопрос, чтобы получить ответ? )) Хорошо, я сейчас, потому что я прочитал все документы о моделировании данных и все еще есть вопросы по этому поводу - person android51130; 13.11.2017
comment
Такое досадное отсутствие базовой функциональности заставляет меня сожалеть о том, что я выбрал Google Firebase в качестве BaaS. - person Andrey Gordeev; 22.11.2017
comment
Здесь нет минных полей. Как и в любой базе данных nosql, вы должны научиться моделировать свои данные таким образом, чтобы они соответствовали вашим ожидаемым запросам. - person Doug Stevenson; 23.11.2017
comment
Итак, я сделал приложение для создания статей. Я был удивлен, когда не нашел решения, как показать список статей, созданных другими пользователями. локальная фильтрация - фигня на миллион (всего одну!) статей. ^ ( - person android51130; 28.11.2017
comment
Я отредактировал ответ, включив в него вариант, который может быть не сразу очевиден - использование запросов для исключения одного значения из диапазона. - person Doug Stevenson; 28.11.2017
comment
А если это не число, а идентификатор (буквенно-цифровой)? Это очень раздражает. - person b-fg; 05.04.2018
comment
@ b-fg Вы можете использовать ту же стратегию. - person Doug Stevenson; 06.04.2018
comment
Запросы диапазона для буквенно-цифровых значений? Покажите мне, пожалуйста, пример. - person b-fg; 06.04.2018
comment
@ b-fg Это похоже на числа, за исключением того, что вы используете строки. Здесь ничего особенного не происходит - это стандартное лексигографическое сравнение строк. - person Doug Stevenson; 06.04.2018
comment
@DougStevenson Сравнение строк не работает для меня. Я получаю пустой ответ, когда использую два предложения where с ›и‹. - person Ari; 20.09.2018
comment
Для новичков этот ответ уже устарел. Проверьте мой ответ ниже, чтобы получить актуальный ответ. - person TSR; 13.09.2020
comment
@TSR этот ответ не устарел. То, что вы рекомендуете в своем ответе, - это не фильтр неравенства, который дает все, кроме определенного значения, как запрашивает OP. Он реализует запрос для набора определенных значений. - person Doug Stevenson; 13.09.2020
comment
Можете ли вы объяснить, что дальше @DougStevenson я пытался реализовать! = Query, но, как ни странно, он просто возвращает элементы, которые логически == для запрошенного атрибута / значения - person David Seek; 22.09.2020
comment
@DavidSeek Если у вас есть конкретный запрос, который не работает должным образом, отправьте новый вопрос, который иллюстрирует проблему и который может воспроизвести любой желающий. - person Doug Stevenson; 22.09.2020
comment
@DougStevenson stackoverflow.com/questions/64001492/ - person David Seek; 22.09.2020
comment
Ничего. Я идиот. Получил неправильный узел. Сохраняет обновление статуса на правильный узел. Вот почему я получал один и тот же элемент снова и снова. Хорошо. Это день, когда я не вернусь ... - person David Seek; 22.09.2020
comment
Теперь фильтр неравенства != доступен в firebase sdk, но, похоже, не работает. - person Midou; 23.09.2020
comment
@Midou Если у вас есть вопрос, опубликуйте его отдельно вместе с кодом, который работает не так, как вы ожидаете, и описанием того, что он должен делать вместо этого. - person Doug Stevenson; 23.09.2020
comment
@DougStevenson Знаете ли вы, ожидается ли обновление официальных документов и включение этих новых фильтров? WereFilterOp Ref не упоминает их. Кроме того, Руководство по запросам по-прежнему говорит, что != не поддерживается. Мне особенно интересно узнать больше о последствиях для индексации и безопасности, связанных с этими новыми фильтрами. Кажется, это ужасно большая функция, которую стоит опустить, а затем оставить лишь пару подсказок в примечаниях к выпуску! - person CDoe; 25.09.2020
comment
@CDoe Я предлагаю обратиться в службу поддержки Firebase, если у вас есть вопрос, который может решить только команда Firebase. support.google.com/firebase/contact/support - person Doug Stevenson; 25.09.2020
comment
отредактируйте свой ответ, это реально, запросы NE активны firebase.googleblog.com/2020/09/ - person Ruli; 02.10.2020

Для Android это должно быть легко реализовать с помощью Task Api. Пример для новичка:

    FirebaseFirestore db = FirebaseFirestore.getInstance();
    Query lessQuery = db.collection("users").whereLessThan("uid", currentUid);
    Query greaterQuery = db.collection("users").whereGreaterThan("uid", currentUid);
    Task lessQuery Task = firstQuery.get();
    Task greaterQuery = secondQuery.get();

    Task combinedTask = Tasks.whenAllSuccess(lessQuery , greaterQuery)
                             .addOnSuccessListener(new OnSuccessListener<List<Object>>() {
        @Override
        public void onSuccess(List<Object> list) {

            //This is the list of "users" collection without user with currentUid
        }
    });

Кроме того, с его помощью вы можете комбинировать любой набор запросов.

Для Интернета есть rxfire

person Jurij Pitulja    schedule 09.08.2019
comment
это лучшая практика? Какие есть другие решения, если я использую адаптер подкачки firestore из firebase-ui - person Sabeeh Ul Haq; 18.03.2020

Это пример того, как я решил проблему в JavaScript:

let articlesToDisplay = await db
  .collection('articles')
  .get()
  .then((snapshot) => {
    let notMyArticles = snapshot.docs.filter( (article) => 
      article.data().owner_uid !== request.auth.uid
    )
    return notMyArticles
  })

Он извлекает все документы и использует Array.prototype.filter () для фильтрации тех, которые вам не нужны. Это может быть запущено на стороне сервера или на стороне клиента.

person Darren G    schedule 29.02.2020
comment
Вы подсчитывали чтения из своей базы данных в консоли Firebase? Я думаю, что таким образом вы всегда читаете весь график db 'atricles' и только затем фильтруете элементы - что слишком дорого для памяти вашего сервера + использование процессора в случае огромного размера графа - person android51130; 01.03.2020
comment
Да, как указано, это решение считывает все документы из коллекции. Не подходит для больших коллекций. Вы можете фильтровать по дате, чтобы получать статьи, скажем, за последнюю неделю, только для уменьшения размера, но это зависит от варианта использования. - person Darren G; 02.03.2020

Обновление ответа Даррена Г., вызвавшего ошибку TypeError: преобразование круговой структуры в JSON. Когда мы выполняем операцию фильтрации, весь объект firebase был добавлен обратно в массив, а не только данные. Мы можем решить эту проблему, связав метод фильтрации с методом карты.

let articles = []
let articlesRefs = await db.collection('articles').get();

articles = articlesRefs.docs
           .filter((article) => article.data.uid !== request.auth.uid) //Get Filtered Docs
           .map((article) => article.data()); //Process Docs to Data

return articles

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

person Ashfaq nisar    schedule 19.07.2020

  1. Отслеживайте все идентификаторы пользователей в одном документе (или двух)

  2. отфильтровать нежелательные идентификаторы

  3. Используйте где в


var mylistofidwherenotme =  // code to fetch the single document where you tracked all user id, then filter yourself out


database.collection("articles").where("blogId", "in", mylistofidwherenotme)

person TSR    schedule 13.09.2020
comment
вы не можете отфильтровать нежелательные идентификаторы из документа, а также не можете каждый раз получать все идентификаторы для локальной фильтрации - мы говорим об огромной базе данных - person android51130; 16.09.2020

let query = docRef.where('role','>',user_role).where('role','<',user_role).get()

Это не работает как операция "не равно" в firestore со строковыми значениями.

person BLasan    schedule 02.09.2019
comment
Я не думаю, что цепочка .where будет работать как логика ИЛИ, она должна быть логикой И. Так что, вероятно, это не сработает? - person Hao-Cher Hong; 23.09.2019
comment
Вы должны отдельно запрашивать оба условия и результаты соединения, тем самым увеличивая количество операций чтения и высасывая деньги из вашего кармана. - person Voonic; 26.01.2020
comment
вернет пустой список - person Tony O'Hagan; 15.06.2020

Вы можете фильтровать массив объектов в коде javascript.

var data=[Object,Object,Object] // this is your object array
var newArray = data.filter(function(el) {
   return el.gender != 'Male';
});
person Kanishka    schedule 13.04.2020

Во Flutter с Firestore выполните запрос с неравенством / не равно, как это

          FirebaseFirestore
          .instance.collection("users")
          .where("uid", isNotEqualTo: auth.currentUser.uid)
          .snapshots(),
person Praveen Kumar    schedule 14.06.2021