Использование Firestore содержит на нескольких полях - PullRequest
0 голосов
/ 01 ноября 2018

У меня есть приложение для видеоигр. Релиз игры может выходить на нескольких платформах. Я слышал, что FireStore гораздо более гибок, чем база данных Firebase в реальном времени, о том, как вы можете получить свои данные. Я застрял на том, как я могу проверить, содержат ли мои документы выпуска игр в моей коллекции релизов выбранные пользователем платформы, поэтому приложение может показывать игры, выходящие на его платформах.

Это то, что у меня сейчас есть

platforms - список целых чисел, содержащий идентификаторы платформ

  databaseReference.collection(getRegionNode())
            .whereEqualTo("m_y", monthFilter)
            .whereArrayContains("platforms", platforms)
            .orderBy("date", Query.Direction.ASCENDING).get().addOnCompleteListener(listener);

Вот пример документа выпуска игры:

   1369: { 
        "src": "Images/dead.png",
        "name": "red dead 2",
        "date": 2018-10-26,
        "region": worldwide,
        "platforms": "[12, 13, 54]"
    }

Допустим, например, что пользователь хочет показывать только игры на платформах 12 и 13, я хочу запрос, который проверяет и извлекает все документы выпусков, где 12 и 13 находятся на их платформах список. Спасибо!

1 Ответ

0 голосов
/ 01 ноября 2018

Firestore Query's , где ArrayContains (строковое поле, значение объекта) :

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

Согласно вашим комментариям, ваш platforms объект, который передается в качестве второго аргумента этому методу, имеет тип array. Что вы на самом деле делаете, вы ищете в свойстве platforms, которое имеет тип массив для массива, что невозможно, поскольку массив платформ в вашей базе данных содержит числа:

"platforms": "[12, 13, 54]"

И , а не массивов. Такой запрос:

databaseReference.collection(getRegionNode())
        .whereEqualTo("m_y", monthFilter)
        .whereArrayContains("platforms", 12) //Passed a number as the second argument
        .orderBy("date", Query.Direction.ASCENDING).get().addOnCompleteListener(listener);

Будет работать нормально, потому что мы ищем число в массиве platforms. Также обратите внимание, что если вы намереваетесь использовать этот король запроса, требуется index. О том, как создать индекс, смотрите мой ответ из этого сообщения .

Даже если вы используете вышеупомянутый запрос, вы можете отфильтровать ваши элементы, используя только один вызов whereArrayContains() метода. Если вы будете использовать более одного, произойдет следующая ошибка:

Причина: java.lang.IllegalArgumentException: недопустимый запрос. Запросы поддерживают только наличие одного фильтра, содержащего массив.

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

Ваша схема должна выглядеть так:

1369: { 
    "src": "Images/dead.png",
    "name": "red dead 2",
    "date": 2018-10-26,
    "region": worldwide,
    "platformsOne": 12,
    "platformsTwo": 13,
    "platformsThree": 54
}

Чтобы найти все игры для платформы 12, 13 и 54, вы должны использовать запрос, который выглядит следующим образом:

FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
Query query = rootRef.
    .whereEqualTo("platformsOne", 12)
    .whereEqualTo("platformsTwo", 13)
    .whereEqualTo("platformsThree", 54);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...