1

How can I make a query to get all bookings of all users that have timestamp in the range of 1519912278 ...1520689878 ? In Firebase docs it states that I can query deeply nested children.

According to this answer, it should work https://stackoverflow.com/a/47805607 , but it return null.

What is the flow of my User app? :
1. User singn up
2. When booking is made, it is saved at /Users/UID/stripe_customer_created_with_card/bookingNumber{booking object}

Why do I need all bookings located under /Users?:
There is a second app designed for Workers which can observe /Users node and each worker should be able to get bookings from /Users based on a timeStamp. For example a worker1382 can read bookings made by /Users from 16 March 2018 to 24 March 2018.

dbRef = FIRDatabase.database().reference().child("Users")
dbRef.queryOrdered(byChild: "TimeStampDateAndTime")
     .queryStarting(atValue: "1519912278")
     .queryEnding(atValue: "1520689878")
     .observeSingleEvent(of: .value, with: { (snapshot: FIRDataSnapshot) in         
        print(snapshot.value) //returns null
     }

 Users
   UID
    cus_CRC50bSq7rXuHv         //stripe customer id for the user
       617643762                //booking number
         TimeStampDateAndTime: "1521309610"
         Postcode: "E14 9DS"
         BookingNumber:"617643762"

Another question: The parent key of the booking object is equal to BookingNumber. If I replace the parent key 617643762 with TimeStampDateAndTime value 1521309610, would I be able to order the bookings by time stamp and ultimately get only the ones that are within a certain range 1519912278 ...1520689878? So, the path would look like Users/UID/cus/1521309610: {object goes here}

From Firebase Documentation

Queries can also be ordered by deeply nested children, rather than only children one level down. This is useful if you have deeply nested data like this:

{
  "lambeosaurus": {
    "dimensions": {
      "height" : 2.1,
      "length" : 12.5,
       "weight": 5000
     }
   },
}

To query the height now, we use the full path to the object rather than a single key. Now, my question is, what can't I do if I don't know the full path?

 let ref = Firebase(url:"https://dinosaur-facts.firebaseio.com/dinosaurs")
 ref.queryOrderedByChild("dimensions/height").observeEventType(.ChildAdded, withBlock: { snapshot in
 if let height = snapshot.value["height"] as? Double {
     println("\(snapshot.key) was \(height) meters tall")
   }
})

EDIT 2

Initial Structure looks like this:

 {
 "Users" : {
    "I50dHN7wPqPJClPfYDG76gXizdD2" : { //-> user?.uid of a logged in user 
       "cus_CRC50bSq7rXuHv" : {
         "617643762" : {
             "TimeStampDateAndTime" : "1521309610"
          }
        }
     }
   }
 }

Modified structure:

{
 "Users" : {
   "I50dHN7wPqPJClPfYDG76gXizdD2" : {
       "1521309610" : { // -> store timeStamp as the immediate child key of UID rather than the booking number
         "TimeStampDateAndTime" : "1521309610",
          "BookingNumber": "617643762"
      }
    }
  }
}


 {
   "UsersProfile":{
     "I50dHN7wPqPJClPfYDG76gXizdD2":{
        "StripeCustomer":"cus_CRC50bSq7rXuHv", // -> store StripeCustomer on the UsersProfile
        "Name": "John Doe"
      }
   }
}
9
  • Well, you are defining ref and then observing on finalRef. Also, your data structure is one level too deep for this query - if TimeStampDateAndTime was a child of the bookings node it would work. Commented Mar 15, 2018 at 20:05
  • While the ref and finalRef issue has been corrected, the problem still exists in that your firebase structure is too deep for that query. You will need to either create a different node to use that query with or re-structure your current structure to support that query. Firebase supports deep queries but the database has to be structured correctly for that to work. See this question for an example structure and a query that supports it. Commented Mar 16, 2018 at 13:01
  • What are the Users keys? I mean firebase query works with auto generated keys. Commented Mar 16, 2018 at 13:02
  • Oh and see Deep Query for another question and answer that should help. On that one, review @frankvanpuffelen answer but then check out the structure and query in my follow up answer. It's ObjC but the structure is in the format that works for deep queries. Commented Mar 16, 2018 at 13:05
  • @TheTiger UID == FIRUser?.uid Commented Mar 16, 2018 at 13:20

1 Answer 1

3

You can query properties at a known path under each child node. So you can query dimensions/weight in the dinosaur sample, and you can query 617643762/TimeStampDateAndTime from your data.

But you can't query */TimeStampDateAndTime, since that's not a known path.

If you need to get a list of bookings in a date range across all users, you will need to modify your data structure to allow that query. For example, by adding a top-level list of bookings:

"Bookings": {
    "book_617643762"
        Customer: "cus_CRC50bSq7rXuHv"
        TimeStampDateAndTime: "1521309610"
        Postcode: "E14 9DS"
}

With this additional structure, you can then query:

dbRef = FIRDatabase.database().reference().child("Bookings")
dbRef.queryOrdered(byChild: "TimeStampDateAndTime")
     .queryStarting(atValue: "1519912278")
     .queryEnding(atValue: "1520689878")
     .observeSingleEvent(of: .value, with: { (snapshot: FIRDataSnapshot) in         
        print(snapshot.value) //returns null
     }
Sign up to request clarification or add additional context in comments.

7 Comments

If I had the structure like this /Users/UID/timeStamp:{booking Object} would I be able to get the bookings that have the child node timeStamp within a time stamp range ? I wrote in my last comment in my original question a more elaborate explanation. Thank you.
That depends on what {booking Object} looks like. The rules are simple: the property you want to order/filter on must be at a fixed path under each child. If it is, you can order/filter on it. If it is not on a fixed path, you can't order/filter on it.
The bookingObject would look like /Users/UID/timeStamp: {Customer: "cus_CRC50bSq7rXuHv", TimeStampDateAndTime: "1521309610", Postcode: "E14 9DS"}
It looks like FIRDatabase.database().reference("Users").queryOrdered(byChild: "timeStamp/TimeStampDateAndTime").queryStarting(atValue: "1519912278").queryEnding(atValue: "1520689878") should work there. If not, edit your question to include the exact JSON (which you can export as text from your Database console) and code you use and we can have a look.
Please see EDIT 2 in my original question. In this path FIRDatabase.database().reference("Users").queryOrdered(byChild: "timeStamp/TimeStampDateAndTime") , timeStamp is not the name of the child, but a variable time stamp of type Int, like 1521309610
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.