Google Could Firestore order string field like number - firebase

i am trying to order a field in Firestore which is a string, but contains numbers. Can i somehow specify the ordering method or customise it?
** Edit 1:
The order i am getting is like this:
1 -> 10 -> 100 -> 101
But i want:
1 -> 2 -> 3 -> 4

If you have a need for strings to behave like numbers, you're using the wrong data type. Use numbers when you need numeric behavior. It sounds like you may have to rewrite all your documents and update your code to properly type the data.
In short, no, you can't do what you're asking (without making a change, or reordering the documents on the client).

I was trying to order items in my Firestore Recycler by querying a number value field and the app was crashing.
So i tried :
Query query = placesRef.orderBy( String.valueOf("likesNum"), Query.Direction.DESCENDING).limit(5);
And it worked. Although the compiler is saying String.valueOF() is not necessary, my problem is perfectly solved.
Maybe that helps someone with same issue.

query = placesRef.orderBy( String.valueOf("likesNum"), Query.Direction.DESCENDING).limit(5);
This only works because when you order by String, the limit is 9 items. Nothing will show up again after that so the best way is to store the field as a number.

Related

Why is 100 in front of 11 in firebase documents order?

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));

Aggregations in Marklogic 8 Java

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.

How to use cursors for navigating to previous pages using GQL and the new gcloud-java API?

I'm using the new gcloud-java API (https://github.com/GoogleCloudPlatform/gcloud-java/tree/master/gcloud-java-datastore/src/main/java/com/google/cloud/datastore) for working with the Cloud Datastore. My specific question is on using GQL for pagination with cursors. I was able to page through the results one page at a time in the forward direction using cursors, but not having any luck with paging backwards.
Example Scenario:
Let's say I've 20 entities in a Kind with IDs 1 through 20. I have a page size of 5. Once I'm on the 3rd page (IDs 11 through 15), if I need to go one page back; i.e. retrieve IDs 6 through 10, what would be the correct GQL/sample code? Again, I prefer not to use offset with a number, but would like to use Cursors.
From what I can tell (actually tested), it looks like one needs to keep track of Start/End cursors for each page as they navigate in the forward direction, then use the saved cursors when there is a need to go back. I just want to make sure if this is the correct/only way or there is a simpler way to accomplish this.
Thanks in advance for your help.
If you add to your original query a sort by key (appended to the end of your "order by" clause), you should be able to reverse each property's sort order and use the latest cursor from your original query to get results in reverse.
Suppose you've iterated through some of the values from your forward query's QueryResults. You can call QueryResults's cursorAfter() method, which will return a cursor pointing right after the last result you saw from your original query. Now you can issue a new query (with the opposite sort order on each property, including the key property) using that cursor as the start cursor. You'll probably want to skip the first result, since it will be the last result you saw from the original query.

How to query for existence of child array in Firebase?

Hello Internet Denizens,
I'm using Firebase at the moment and am trying to query the following structure:
items
1
- name: "Car"
- Children
- 2
- 3
2
- name: "Wheels"
3
- name: "Engine"
You can see from this example that I have an array of items with Ids of 1,2, & 3. 1 also has its own sub-array called Children, which is composed of Ids 2 & 3.
How would I make a firebase query that pulled back only the Ids which had an array called children?
At first, I thought something like the following would work:
<my firebase path>.child('items').orderByChild('Children').once('value', function(snap){
// ... No results :(
});
No luck. Next, I tried adding an attribute called hasChildren = true to the Id of 1 and then queried like so.
<my firebase path>.child('items').orderByChild('hasChildren').equalTo(true).once('value', function(snap){
// ... iterate over results, which in this case is the Id 1
});
However, when I do a snap.ForEach(function(data)... and then look at data.val().Children, it's just a blank result, which confuses me because I thought Firebase pulled back all child nodes. Hence, the need to flatten your data.
How do I get those Children values?
** Update ** Plunker Added
http://plnkr.co/edit/9U0ujEwdKi7sgQGmd6IE?p=preview
Looks like this was a comedy of errors.
1) In the simple example, 1, 2, & 3 are ordered, so firebase treats it as an array. In the real world, those numbers are much more random so firebase treats them as an object since they aren't ordered.
2) For some reason, Intellij wasn't showing the Children object's contents. I had to type in something like data.val().Children['3'] to get a value or something like for(var property in data.val().Children) to iterate through the fields. Weird.
3) I STILL can't do .child('items').orderByChild('Children') ... since that returns all records. Oddly enough, however, it returns the ones that have Children first.
DataSnapshot.forEach returns another snapshot in the callback. So instead of trying to access data['Children'], you would have to use data.val().Children.
Looks like modifying my data structure is the best way to go since checking for the existence of an array object isn't possible at this point.

How to list unique values of a particular field in Kibana

I am having a field named rpc in my elasticsearch database and I am displaying it using Kibana. When I search in search bar of kibana like:
rpc:*
It display all the values of rpc field but I want to have only those value to be displayed which are unique.
I have been playing around with Kibana4 since a couple of weeks now. I find it intuitive and simple and the experience has been great till now. Following your question, I tried getting unique results via a Data Table visualization. Why? Because I personally find it easier to understand. Following are the steps:
1. Get unique count
Create the visualization (Visualize -> Data Table). First lets get
the count of how many unique entries we have for a particular field
(We will use this in the later part for verification). I'm using
clientip.raw but as I see, it will work just fine with any friendly
field name too.
2. Set the aggregation right
Set you aggregation back to count and have a Split Rows as follows. Not doing this will give you count 1 for each field value (since it is looking for unique counts) when you populate the table. Noteworthy part is setting the Top field to 0. Because Kibana won't let you enter anything else than a digit (Obviously!). This was the tricky part. Hit Apply and you'll get the results. Unique field values and the count of each of them.
3. Verification:
Going to the last page of the table, we see there are exactly 543 results. This is how I know it works.
What Next?
You save this visualization and add it to a Dashboard. There you can always check the request, query, response and other stats.
Just an addition to the above mathakoot answer.
For the user of newer version (which do not allow bucket size of 0 anymore) just set a value greater than the maximum number of result
And report the value in the Options>Per Page field
I am using Kibana 6 so the UI looks a bit different than the older answers here.
Here is what worked for me
Create a visualization from your query, I used a line graph type (don't think it matters)
Under Data, set metrics aggregation = "Unique Count" and set field to your field.
Set x-axis aggregation = "Terms" and set field to your field.
Set Size > your number of records
Under Metrics and Axes, disable drawing of the graph, circles, and labels (this really helps the UI not lag)
Run query and then click "Inspect" and download CSV
Data
Metrics & Axes
I wanted to achieve something similar but I'm stuck with Kibana 3.1.
I simply added a panel of type "TERMS" and configured its Field = User-agent and left everything else on default values. This gave me a nice bar chart with one bar for each User-agent.

Resources