Incrementing Number as Firestore Document Name? - java

Basically summed up in the title, I would like to make it so that each new document being created in a particular collection has an increment sort of serial number to it. This is for properly tracking the new orders that are written to the database. AutoID is random and causes sorting issues, I would like the data to be easily manageable. Is this possible to achieve via Cloud Functions? Any sample code snippets I can look at? Thank you!

Use firebase.firestore.FieldValue.serverTimestamp. It will be set by the server to nanosecond resolution.
firebase.firestore().collection('stuff').add({
sort: firebase.firestore.FieldValue.serverTimestamp(),
});

As per #Frank van Puffelen comment, "Using sequential IDs for that is an anti-pattern". Your use case is also mentioned in the Firestore documentation here:
Important: Unlike "push IDs" in the Firebase Realtime Database, Cloud
Firestore auto-generated IDs do not provide any automatic ordering. If
you want to be able to order your documents by creation date, you
should store a timestamp as a field in the documents.

Related

How to search Firebase database by any field?

Is there any way I could search by any Reatime Firebase Database field? Right now I know how to search by FP_CarNumber, but I would like to search by others as well like SP_CarNumber or SP_CarNumber and FP_CarNumber at the same time.
private void txtSearch(String str){
FirebaseRecyclerOptions<MainModel> options =
new FirebaseRecyclerOptions.Builder<MainModel>()
.setQuery(FirebaseDatabase.getInstance().getReference().child("Declaration_Data").child(currentuser).child("Declarations").orderByChild("FP_CarNumber").startAt(str).endAt(str + "\uf8ff"), MainModel.class)
.build();
mainAdapter = new MainAdapter(options);
mainAdapter.startListening();
recyclerView.setAdapter(mainAdapter);
}
The Realtime Database only supports queries on single field property. I have explained in one o my answers:
How to sort Firebase records by two fields (Android)
How to solve such a situation by creating an extra field to keep the other values. Unfortunately, that workaround doesn't apply to all situations.
Besides that, as far as I know, there is no library that does that automatically in Android. However, there is one for the web, written by David East called Querybase.
So unlike in the Realtime Database, Cloud Firestore allows compound queries. So I recommend you try that.

Is it possible to compare two collections in Firestore?

I'm developing an Android app with Java and using Firestore, It's a social network and I have a collection with all the posts. I'm trying to show only those posts that belong to the followed users, so I make a query to show all the posts ordered by timestamp, but I don't know if I can filtered them by comparing with the collection "followed" inside "User".
The main collection "Users" has documents, each of them is a user, inside every user there is a subcollection "followed" that contains the followed users, every document is a user and the document id is the same that the User ID.
The posts are stored in another main collection called Posts, so I need to compare the id User inside "Posts" documents with the id of the docs in the subcollection "followed". I hope somebody can help me, I spent a lot of time and I can't find anything, thank you.
Firestore does not have the ability to "join" documents in collections as you're describing here. It's relatively straightforward in SQL (if your server has enough memory), but Firestore (and other NoSQL databases) aren't built for this, due to its distributed nature, and the way it needs to scale.
The only way to do what you want is to write code to read every document in every collection that would need a comparison, and also perform that comparison with the documents in memory.

Firestore generated key versus custom key in a collection?

I am using Cloud Firestore database in my Android app and I have different documents within collections like: uid for users, pushed keys for restaurants and numbers for my recipes.
My db:
users
uid1
uid2
...
resturants
pushedId1
pushedId2
...
recipes
0001
0002
...
For the users I understand to use the uid's but is better to use Firestore pushed ids for my restaurants? Is this a convention or why to use it?
I also tried to generate unique keys using UUID Class but is more easy for me to use only numbers for my recipes. Is this a bad approach?
Any help will be appreciated, thank you!
By using predictable (e.g. sequential) IDs for documents, you increase the chance you'll hit hotspots in the backend infrastructure. This decreases the scalability of the write operations.
Cloud Firestore has a built-in generator for unique IDs, that is used when you call CollectionReference.add(...) or CollectionReference.document() (without parameters). The ID that it generates is random and highly unpredictable, which prevents hitting certain hotspots in the backend infrastructure.
Using UIDs for the documents of users is a fine substitute for Firestore's built-in generator, since the UIDs already have a high level of entropy: you can't predict the UID of the next user based on knowing the current user. In such a case, using the UID (or otherwise the natural key of the entity) is a better approach, since you can perform direct lookups of the documents instead of having to query.
See this discussion on the firebase-talk mailing list where some of the engineers working on Firestore explain in more detail.
First of all there are no pushed id's in Firestore. We use the push() method in Firebase Realtime database. In Cloud Firestore we pass no argument to the document() method in order to generate a unique id for a document.
In case of users, the best unique identifier is the uid. In case of other collections like resturants, recipes or any other collection, you should consider using the id's that are generated by Firestore.
Unlike in Firebase Realtime database where there is an astronomically small chance that two users can generate a push ID at the same exact period of time and with the same exact randomness, in Cloud Firestore the IDs are actually purely random (there's no time component included).
And as an answer, you should definitely use the random keys that are generated by Firestore. Don't use simple numbers as keys for your documents.
Edit: Using sequential IDs is an anti-pattern when it comes to Firebase. Is not recommended to use this tehnique in Cloud Firestore nor in Firebase Realtime database, since it will cause scalability problems. To benefit from one of its most important features in Firestore, which is scalability, you should consider not doing this. Scalability is one of Firestore key features and it comes from how Firestore spreads the document out over its storage layer.
Using other tehniques rather than what Firestore offers, increase the hashing collisions, which means you hit write limitations in a shorter time. Having absolut random ids ensures that the writes are spread out evenly across the storage layer.

Get all documents from Couchbase bucket

I am writing Couchbase DAO using Java API. I store all documents for one entity in particular bucket. I wonder what is the best way to get all documents from this bucket?
Thanks in advance!
First: do you plan to store each entity type in their own buckets? That will probably not work in the long run, unless you plan to only ever have no more than 10 total entities. Buckets are not made to organize data like that: they are meant to store a variety of different types of data.
Second: do you really want to get all data from a bucket? That seems like a very uncommon use case. It's almost like asking "how do I query all data from all tables in a relational database"
That being said, I could imagine a very specialized situation where you'd want to do this. So, you could:
Create a PRIMARY index and execute a N1QL query like SELECT * FROM mybucket;
Create a very simple map/reduce view index of the data.
Both of these things can be done with the Java SDK.

persisting dynamic properties and query

I have a requirement to implement contact database. This contact database is special in a way that user should be able to dynamically (on runtime) add properties he/she wants to track about the contact. Some of these properties are of type string, other numbers and dates. Some of the properties have pre-defined values, others are free fields etc.. User wants to be also able to query such structure fast and easily. The database needs to handle easily 500 000 contacts each having around 10 properties.
It leads to dynamic property model having Contact class with dynamic properties.
class Contact{
private Map<DynamicProperty, Collection<DynamicValue> values> propertiesAndValues;
//other userfull methods
}
The question is how can I store such a structure in "some database" - it does not have to be RDBMS so that I can easily express queries such as
Get all contacts whose name starts with Martin, they are from Company of size 5000 or less, order by time when this contact was inserted in a database, only first 100 results (provide pagination), where each of these segments correspond to a dynamic property.
I need:
filtering - equal, partial equal, (bigger, smaller for integers, dates) and maybe aggregation - but it is not necessary at this point
sorting
pagination
I was considering RDBMS, but this leads more less to this structure which is quite hard to query and it tends to be slow for this amount of data
contact(id serial pk,....);
dynamic_property(dp_id serial pk, ...);
--only one of the values is not empty
dynamic_property_value(dpv_id serial pk, dynamic_property_fk int, value_integer int, date_value timestamp, text_value text);
contact_properties(pav_id serial pk, contact_id_fk int, dynamic_propert_fk int);
property_and_its_value(pav_id_fk int, dpv_id int);
I consider following options:
store contacts in RDBMS and use Lucene for querying - is there anything that would help with this?
Store dynamic properties as XML and store it to rdbms and use xpath support - unfortunatelly it seems to be pretty slow for 500000 contacts
use another database - Mango DB or Jackrabbit to store this information
Which way would you go and why?
Wikipedia has a great entry on Entity-Attribute-Value modeling which is a data modeling technique for representing entities with arbitrary properties. It's typically used for clinical data, but might apply to your situation as well.
Have you considered using Lucene for your querying needs? You could probably get away with just using Lucene and store all your data in the index. Although I wouldn't recommend using Lucene as your only persistence store.
Alternatively, you could use Lucene along with a RDBMS and take advantage of something like Compass.
You could try other kind of databases like CouchDB which is a document oriented db and is distributed
If you want a dumb solution, for your contacts table you could add some 50 columns like STRING_COLUMN1, STRING_COLUMN2... upto 10, DATE_COLUMN1..DATE_COLUMN10. You have another DESCRIPTION column. So if a row has a name which is a string then STRING_COLUMN1 stores the value of your name and the DESCRIPTION column value would be "STRING_COLUMN1-NAME". In this case querying can be a bit tricky. I know many purists laugh at this, but I have seen a similar requirement solved this way in one of the apps :)

Categories