Поисковый массив Firestore содержит несколько значений - PullRequest
0 голосов
/ 04 марта 2019

Если у меня есть простая коллекция, например:

Fruits:
  Banana:
   title: "Banana"
   vitamins: ["potassium","B6","C"]
  Apple:
   title: "Apple"
   vitamins: ["A","B6","C"]

И если я хочу найти фрукты, содержащие витамин B6, я бы сделал следующее:

db.collection("Fruits").whereField("vitamins", arrayContains: "A").getDocuments() { (querySnapshot, err)  in
        if let err = err {
            print("Error getting documents: \(err)")
        } else {
            for document in querySnapshot!.documents {
                print("\(document.documentID) => \(document.data())")
            }
        }
    }

И этопокажет мне все фрукты в моей коллекции, которые содержат витамин А. Однако как мне найти фрукты, содержащие несколько витаминов, скажем, витамины В6 и С?Я не могу просто выполнить поиск ["B6","C"], так как он будет искать массив в отличие от независимых строк.

Возможно ли это даже в Cloud Firestore?Если нет, есть ли альтернативный способ сделать это?

Ответы [ 3 ]

0 голосов
/ 04 марта 2019

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

Invalid Query.Запросы поддерживают только наличие одного фильтра, содержащего массив.

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

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

vitamins: { 
    "potassium": true,
    "B6": true,
    "C": true
}

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

let fruitsRef = db.collection("Fruits")
    .whereField("vitamins.potassium", isEqualTo: true)
    .whereField("vitamins.B6", isEqualTo: true)
    .whereField("vitamins.C", isEqualTo: true)
0 голосов
/ 04 марта 2019

Нет способа выполнить несколько запросов, содержащих массив, как вы спрашиваете в Firestore.Однако вы можете комбинировать столько условий where, сколько практически возможно.Поэтому рассмотрим следующее:

Fruits:
    Banana:
        title: "Banana"
        vitamins:
            potassium: true
            b6: true
            c: true

Firestore.firestore().collection("Fruits").whereField("vitamins.potassium", isEqualTo: true).whereField("vitamins.b6", isEqualTo: true)

Это, однако, не позволяет сделать чистую orпоиск, просто and.Чтобы запросить фрукты с витамином-х или витамином-у, вам нужно стать более креативным.Кроме того, этот подход не следует использовать в ситуациях, когда имеется «много» возможных значений, и их необходимо объединять с составными запросами.Это потому, что Firestore не допускает более 200 составных индексов, и каждый составной индекс должен указывать точный витамин.Например, вам нужно создать отдельный составной индекс для vitamins.b6, vitamins.potassium и т. Д., И всего у вас будет только 200.

0 голосов
/ 04 марта 2019

Было бы заманчиво искать документы, которые соответствуют нескольким условиям, путем объединения условий в запросе:

db.collection("Fruits")
    .whereField("vitamins", arrayContains: "B6")
    .whereField("vitamins", arrayContains: "C")

Но документация для составных запросов предполагает, что вы не можетев настоящее время есть несколько массивов. Содержит условия в одном запросе.

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

Fruits:
  Banana:
   title: "Banana"
   vitamins: {
     "potassium": true,
     "B6": true,
     "C": true
   }

Тогда вы можете сделать запрос следующим образом:

db.collection("Fruits")
    .whereField("vitamins.B6", isEqualTo: true)
    .whereField("vitamins.C", isEqualTo: true)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...