Is it possible to do wildcard queries on Firebase? For example:
https://foo.firebaseio.com/person.json?orderBy="name"&equalTo="Lun*"
I know it's been a while but I thought that others might be interested. You can "fake" a wildcard search for things like foo* (so basically you can search for values beginning with a specified string).
For iOS & Swift it would look like this:
dbReference.child("person").queryOrdered(byChild: "name").queryStarting(atValue: "foo").queryEnding(atValue: "foo\u{f8ff}").observe(.childAdded) { (snapshot: FIRDataSnapshot) in
print("\(snapshot.key) - \(String(describing: snapshot.value))")
}
What this does is using a start and end values for name property where the end key is equal to the start + a very high code point in the Unicode range. Because it is after most regular characters in Unicode, the query matches all values that start with foo.
No. But kinda.
You cannot do a wildcard query, however, you can structure your data that will allow for this.
For example, say we want to find matches for users whose name starts with Ler
Here's our structure
users
uid_0
name: "Leroy"
Store the decomposed data in another node: Remember, disk space is cheap.
decomposed
uid_0
L: true
Le: true
Ler: true
Lero: true
Leroy: true
then perform a query on the decomposed node for the value of true for children equal to Ler
ref.queryOrderedByChild("Ler").queryEqualToValue(true).observeEventType(.ChildAdded,
withBlock: { snapshot in
print(snapshot.key)
})
And the snapshot.key will be uid_0
You can do something like this.
Make sure you order your search field alphabetically.
Then you search for all names (starting at Lun and ending at Luo) where the last letter 'o' is calculated with the initial last letter 'n' + 1.
I guess you see the general idea here.
So it should return anything between 'Lun*' and stop at the first entry of 'Luo*'
https://foo.firebaseio.com/person.json?orderBy="name"&startAt="Lun"&endAt="Luo"
Since Firebase doesn't support wildcard searching I decided to go with Apigee BaaS for our company.
Related
I'm building an app that will display a list of user info, with each one a numeric ID that is stored when creating the profile and used as the docID in firebase. To facilitate the search, I used this method so the ID would be displayed in ascending order. But, after some tests, I notice that, for example, 100 comes first then 11. Why does it happen? Is there a way to correct/prevent it?
I was storing ID as String. But, as the answer suggested, I changed it to both int and double. Still, 11 comes after 100
It's hard to say for certain without seeing your database, but most likely you're storing the numbers as strings. In such cases Firebase (both Firestore and Realtime Database) will sort the values lexicographically, and in that order "100" comes before "11" - just as "baa" comes before "bb".
Why is 100 in front of 11 in firebase documents order?
Because you're sorting alphabetically instead of numerically. 0 comes before 1 in most character encodings like ASCII and Unicode.
After the answers I got and some research I finally got it.
The main problem was that I was storing the ID as String.
After fixing it, I added .orderBy('id') in the place where I retrieve the
uses' list.
Thank you everyone one for the time spent trying to help me.
Another way is to perform sorting after you queried. It is not efficient though, but in case you cannot change the data type or ids themselves:
const query = await db.collection("my-collection").get();
query.docs.sort((doc1, doc2) => parseInt(doc1.id) - parseInt(doc2.id));
This latitude should have a '0' at the end, but whenever I add it - Firebase deletes it. Being a coordinate I need it to be exactly 51.3910 not 51.391. Any idea how I'd force Firebase to leave the '0' in there?
From docs you have many options, since you have not added you code, you may try a code like this to solve the issue.
Firebase busCoords = mRef.child("Location");
busCoords.setValue(location.getLatitude()+ ", "+location.getLongitude());
This MUST be working, but you may also try turning the number to a string, which can be done with a code like this:
String numberAsString = String.valueOf( -895.25);
The Firebase Realtime Database uses JSON to store data, so will accept the following data types:
string
number
boolean
array
JSON object
null
The data type for your Latitude node will be considered a number, which does not support trailing or leading zeros.
Therefore, you'll need to manually pad your data when retrieving it from the database, or store it as a string instead.
So having looked into it for hours, I have figured out the problem lied with Google giving me wrong coordinates when I typed in 'example coordinates'. The coordinates were not right and the coordinates I wanted didn't end in a 0!
Thank you for your help.
I'm trying to group all the documents based on an element value. Through X-Query, I'm able to get the element value and its corresponding count. But, with Java API I'm not able to do that.
X-Query:
for $name in distinct-values(doc()/document/<element_name>)
return fn:concat("Element Value:",$name,", Count:",fn:count(doc()/document/[element_name eq $name]));
Output:
Element Value:A, Count:100
Element Value:B, Count:200
Java:
QueryManager qryMgr = client.newQueryManager();
StructuredQueryBuilder qb = new StructuredQueryBuilder();
StructuredQueryDefinition querydef = qb.containerQuery(qb.element("<element_name>"), qb.term("A"));
SearchHandle handle = new SearchHandle();
qryMgr.search(querydef, handle);
System.out.println(handle.getTotalResults());
By this method, I'm able to get the document count only for a particular value. Is there any way to get the count of all documents. Kindly Help!
If I understand your use case, you can use a range index to solve this problem, which is - you want to know what all the values are for a particular element, and then how many documents have that value. That's exactly what a range index is for.
Try adding a range index on "element_name" - you can use the ML Admin app for that - go to your database and click on Element Range Indexes.
In XQuery, you can then do something like this:
for $val in cts:element-values(xs:QName("element_name"))
return text{$val, cts:frequency($val)}
With the Java Client, you can do the same by adding a range-based constraint to a search options file, and then the response from SearchManager will have all of the values and frequencies in it that match your query. Check the REST API docs for constructing such a search options file.
I have a dataset of objects, e.g. cars. I want to make a system where users are presented an object, and can decide whether or not they like the car. But, I want to show them each car only once.
- allCars
- car1
- car2
...
- car348237
- carsLiked
- user1
- carsLiked
- car123
- car234
- carsNotLiked
- car321
- user2
- carsLiked
- carsNotLiked
Given some user, e.g. user1, how can I make a selection from allCars, WHITOUT cars that the user has already seen? In SQL I would do something like " WHERE carId NOT IN (car123, car234, car321) "
Any idea how I can do this in firebase (without filtering on clientside, I know how to do that)...? Any structure possible, using some kind of index.? I struggled for sometime but didn't find a solution.
Denormalization is a key.
I would replicate a set of all cars in each user's object and than I would delete the car object already displayed to user.
cars:{
CAR_AUDO_ID: {
//car object
}
users:{
user1:{
car_selection:{
CAR_AUTO_ID: true //reference to above
...
},
cars_liked:{
},
cars_disliked:{
}
}
coming from SQL it might sound like a lot of replication, but that the way to go with firebase.
in case you have something like 10K+ cars, of course the above would be overkill. If users are presented a random car than I would focus on random number generator where I would store only already picked numbers. In that case the best would be to use priority ordered list and your key would be something like increment counter.
I am trying to use query strings in ASP.NET. I have a requirement of the following format
http://localhost/website/1/?callback=?
Here 1 denotes the ID of the profile. This means some info from id=1 will be fetched through the string
If this would have been website/2/?callback=? , then the id would be 2. My questions is to how do I use this /id/ as a query string so it can be used to fetch the profile ID. This was my first preference to use /id/ format otherwise I could look into fetching using two ?'s
If the id =1, I want to fetch ID=1 particulars from DB on this page. http://localhost/website/1/?callback=?
In your case the ID is in the PATH, not the query string. You can access the path via Request.Path in an ASPX page. From there you would need to do some string parsing to get at the portion of the path where you expect the ID to be.
In your case I would probably use something like int.Parse(Request.Path.Split(new char[] {'/'}, StringSplitOptions.RemoveEmptyEntries)[1]), but please note that I've made that line pretty dense for brevity's sake. For starters, you should use int.TryParse() instead of int.Parse(). This code assumes that the ID will always be in the same place in the url. For example, it will work for "/website/2/" and "/user/2/", but not for "/website/somethingelse/2/".
UriTemplate might be a good choice for that sort of parsing. Not to mention, probably a bit more clear and explicit about what's happening.
Check out: http://msdn.microsoft.com/en-us/library/system.uritemplate(v=VS.90).aspx