Reputation: 195
I wanted to know if it's possible and how you can search through firebase. My app has a textfield where you can fill in some specifications that's get 'saved' in through an array.
for example:
var arrayOfSpecs = ["13'", "Black"]
Now I want to search with 2 segmented options:
Search for the name of one of the Elektronics that has a spec of 13" or is black" (this elektronic device may have other specs; but has to include at least one of the given specs)
Search for the name of one of the Elektronics that only has the specs I wrote, less specs are ok but no more specs than where the person searched for.
Example: Search for "black" "13inch"; the searchResults could include a MacBook with one spec: "black", but it could also include a MacBook Pro with 2 specs: "black" and "13inch", but it can not include a MacBook Air with specs: "Black", "13 inch", "Retina"
The searchResult would come in a tableview, or would store the correct names of the searchResults in array, which I would put in a UITableView
Below my database, I'll hope you understand what I'm looking for.
thanks
Upvotes: 4
Views: 1492
Reputation: 4886
You could also use a SQL solution instead of Key-Value. Firebase is strictly a Key-Value database.
Upvotes: 0
Reputation: 35648
So start off with a products node for all products. The node name is created with childByAutoId.
products
-abcde
name: MacBook
color: black
display: retina
port: Thunderbolt
size: 13
-fghij
name: MacBook Air
color: black
display: standard
port: USB
size: 13
-xxxxx
name... etc etc
Then we divide up the specifications and refer back to the products in each node.
specs
black
13
abcde: true
fghij: true
15
xxxx: true
grey
13
yyyy: true
zzzz: true
15
qqqq: true
13
abcde: true
fghij: true
yyyy: true
zzzz: true
If you want all black, 13" Macs, observeSingleEventOfType of .Value on the
specs/black/13
node which will load in the abcde, and fghij product references.
If you want to get all grey 15 inch laptops, do the same on the
specs/grey/15
node.
If you want all 13 inch laptops observe the
specs/13
node
The beauty of this is you don't need any queries at all since you know specifically what data you are after. Queries are very heavy compared to an observe event.
Another option is to compile the specs into single lines
specs
-abcde
black_13_retina_SSD_Thunderbolt
13_retina_SSD_Thunderbolt
retina_SSD_Thunderbolt
SSD_Thunderbolt
Thunderbolt
.
.
-fgijk
black_13_standard_SSD_USB
13_standard_SSD_USB
etc
Then you can easily query for all models that have SSD_Thunderbolt.
You can also query for all products that startsWith: 13_ and endsWith: 13_
You will need to put the various combinations within each spec so you could query for 13_SSD but if you only have 3 or 4 specs it's not too bad.
Remember - disk space is cheap and don't be afraid to duplicate data in different formats to get back what you want. Also, crafting a parser to read the main product, parse it and dump the specs out in their combinations is pretty simple.
Hope that helps.
Upvotes: 0
Reputation: 9945
Change your JSON Structure to
Electroniks:{
Macbook:{..,
Specification:{
13inch : true,
black : true
},
...
},
iPhone:{..,
Specification:{
13inch : true,
black : true,
camera : true
},
...
},
iPad:{..,
Specification:{
xinch : true,
red : true,
camera : true
},
...
}
}
I don't think you can match two node queries at once , But what you can is, you can match one specification .queryEqualToValue
at a time
So a workaround would be :- retrieve all the parentNodes which have one particular Specification and then iterate through those to match your other Specification
let parentRef = FIRDatabase.database().reference().child("Elektronics")
parentRef.queryOrderedByChild("Specification/black").queryEqualToValue(true).observeSingleEventOfType(.Value, withBlock: {(snap) in
if let dict = snap.value as? [String:AnyObject]{
for each in dict{
print(each.0) //Would retrieve you every product name with colour black in specification i.e Macbook and iPhone
print((each.1["Specification"] as! NSDictionary).count)//Number of specification
parentRef.child("each.0").child("Specification").child("13inch").observeSingleEventOfType(.Value, withBlock: {(snapshot) in
if snapshot.exists(){
print(each.0) //You found your product's with exactly 13inch and black Specification.This is their name
}
})
}
}else{
print(snap.ref)
}
})
Upvotes: 2