Firebase, IN clause query and lists of datas

折月煮酒 提交于 2019-12-13 14:52:49

问题


In my opinion this is pretty obvious question when someone has to deal with a DB, so I don't know why I can't find anything about it.
I'm trying to design the non-relational database for my project. I have a list of products described by some info (e.g. the code, an image and a multi language description) and they are categorized in different ways. Here is a snap of the structure:

"products" : {
    "-JiGh_31GA20JabpZBfa" : {
      "code" : "IR3300000000",
      "schema" : "http://lorempixel.com/400/200/",
    },
    "-JiGh_31GA20JabpZBfb" : {
      "code" : "PJ0000000000",
      "schema" : "http://lorempixel.com/400/200/",
    }
  }

"it" : {
    "products" : {
      "-JiGh_31GA20JabpZBfa" : {
        "description" : "desc product IR330000000"
      },
      "-JiGh_31GA20JabpZBfb" : {
        "description" : "description product PJ00000 lorem ipsum"
      }
    }
  }

And below there are a couple of usages of the products, the real structure is much more complex, but probably it's enough to explain my problem:

"families" : {
    "family1" : {
        "products" : {
            "-JiGh_31GA20JabpZBfa" : true,
            "-JiGh_31GA20JabpZBfb" : true
        }
    },
    "family2" : {
        "products" : {
            "-JiGh_31GA20JabpZBfa" : true
        }
    }
}

"applications" : {
    "application_1" : {
        "products" : {
            "-JiGh_31GA20JabpZBfa" : true,
            "-JiGh_31GA20JabpZBfb" : true
        }
    },
    "application_1" : {
        "products" : {
            "-JiGh_31GA20JabpZBfa" : true,
        }
    }
}

Ok, now let's move to the client side!

I have a couple of tables, one that shows the families and one for the applications of the products. Selecting one of them I want to show all products that belong to the family or that are used in an application.

And here is what I'm struggling with: if I want to show the description and the code of each product in a cell, do I have to perform a query for every product to retrieve their fields or can I use some sort of "IN" query? Something like select * from products where key IN {"-JiGh_31GA20JabpZBfa", "-JiGh_31GA20JabpZBfa"}. I know that it's an SQL like query, but this was just to better explain myself.

Btw, I don't exclude that my way of designing the DB is wrong.


回答1:


As indicated in the first comment by @Frank van Puffelen, there is no way to perform a IN query or, I suppose, something similar to a JOIN.
So here are a few pieces of my code and a brief of the pipeline that I have implemented!

I created 2 UITableViewController, the first one to show the families and the second one to show the products of the selected one.

So, in the first controller I wrote this code to retrieve the list of families:

let ref = FIRDatabase.database().reference()
ref.child("families").observeSingleEvent(of: .value, with: { snap in
    if snap.value is NSNull { return }        
    let families = snap.value as! [String:AnyObject]
    for familyKey in families.keys {
        let familyDetails = familyes[familyKey] as! [String:AnyObject]
        self.families.append(FamilyL1.init(familyName: familyKey, familyDetails: familyDetails))
    }
    self.tableView.reloadData()
})

After the selection of a family, in the second controller I'll perform two queries: one to retrieve the details of the product and the other one for the multi-language description.

for (index, product) in (family?.products ?? []).enumerated() {
    self.ref.child("products").child(product.id).observeSingleEvent(of: .value, with: { snap in
        if snap.value is NSNull { return }
        product.populateProduct(product: snap.value as!  [String:AnyObject])
        self.tableView.reloadRows(at: [IndexPath.init(row: index, section: 0)], with: .none)
    })   
    self.ref.child("it").child("products").child(product.id).observeSingleEvent(of: .value, with: { snap in
        if snap.value is NSNull { return }
        product.populateProductDescription(product: snap.value as! [String:AnyObject])
        self.tableView.reloadRows(at: [IndexPath.init(row: index, section: 0)], with: .none)
    })
}

As suggested, I've taken advantage of the parallelism, so the queries aren't performed sequentially and the interested cells will be refreshed at each update. I've taken care of the optional values to achieve that:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
    let product = self.family?.products[indexPath.row]
    cell.textLabel?.text = product?.code ?? "..."
    cell.detailTextLabel?.text = product?.pDescription ?? "..."
    return cell
}

I hope this answer will help those who are trying to use this great platform!



来源:https://stackoverflow.com/questions/40783240/firebase-in-clause-query-and-lists-of-datas

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!