0

My database looks like this:

{
  "products" : {
    "accessory" : {
      "acc01" : {
        "ean" : 8793462789130,
        "name" : "Some product acc01"
      },
      "acc02" : {
        "ean" : 8793462789134,
        "name" : "Some product acc02"
      }
    },
    "cpu" : {
      "cpu01" : {
        "ean" : 8793462789115,
        "name" : "Some product cpu01"
      },
      "cpu02" : {
        "ean" : 8793462789116,
        "name" : "Some product cpu02"
      },
      "cpu03" : {
        "ean" : 8793462789117,
        "name" : "Some product cpu03"
      }
    },
    "ios" : {
      "ios01" : {
        "ean" : 8793462789120,
        "name" : "Some product ios01"
      },
      "ios02" : {
        "ean" : 8793462789123,
        "name" : "Some product ios02"
      },
      "ios03" : {
        "ean" : 8793462789125,
        "name" : "Some product ios03"
      },
      "ios04" : {
        "ean" : 8793462789123,
        "name" : "Some product ios04"
      }
    }
  }
}

I managed to fetch all the products and store them in an array like so:

static func getAvailableProducts(completion: @escaping ([Product]) -> Void) {
    self.ref.child("products").queryOrderedByKey().observeSingleEvent(of: .value) { (snapshot) in
        var products = [Product]()
        for category in snapshot.children.allObjects as! [DataSnapshot] {
            let productCategory = category.key
            for product in category.children.allObjects as! [DataSnapshot] {
                let identifier = product.key
                if let productCategory = Category(rawValue: productCategory),
                  let ean = product.childSnapshot(forPath: "ean").value as? Int,
                  let name = product.childSnapshot(forPath: "name").value as? String {
                    let productToAdd = Product(identifier: identifier, category: productCategory, ean: ean, name: name)
                    products.append(productToAdd)
                }
            }
        }
        completion(products)
    }
}

Now what I don't understand is how I can get a node with a specific ean code. I tried so far like so:

static func getProduct(by ean: Int, completion: @escaping (Product) -> Void) {
    self.ref.child("products").queryOrdered(byChild: "ean").queryEqual(toValue: ean).observeSingleEvent(of: .value) { (snapshot) in
            if snapshot.exists() {
                // Create product and return with completion
            }
    }
}

Unfortunately the snapshot does not exist – so my query is obviously wrong... I do know that the ean key is one level below, but I do want query all products in all categories.

Any hint is highly appreciated!

appfrosch
  • 1,146
  • 13
  • 36
  • A Firebase Database query returns child nodes directly under the location you query. It cannot skip a level, like is needed in your JSON structure. To allow that query you will need a single-level list with the `acc01`, `acc02`, `cpu01`, `cpu02`, etc. Also see https://stackoverflow.com/questions/27207059/firebase-query-double-nested and https://stackoverflow.com/questions/40656589/firebase-query-if-child-of-child-contains-a-value – Frank van Puffelen Jul 29 '18 at 23:17
  • Thanks for sharing these answers, will try to build an index on those barcodes - and I guess I will have to get rid of my nesting of categories as well. – appfrosch Jul 30 '18 at 04:41
  • If it's useful in other contexts, you might want to keep it and add an additional structure for the flat list. Duplicating data is quite common in NoSQL databases. Also see [Denormalizing your data is normal](https://firebase.googleblog.com/2013/04/denormalizing-your-data-is-normal.html) and [NoSQL data modeling](https://highlyscalable.wordpress.com/2012/03/01/nosql-data-modeling-techniques/). – Frank van Puffelen Jul 30 '18 at 14:04
  • Thanks a lot, I will digest those articles now, but I guess I do have a better understanding in how this is supposed to work already. I appreciate your input. – appfrosch Aug 01 '18 at 08:21

0 Answers0