Exposing Datomic entity identities to a service or REST API - clojure

I’m confused about how to expose the identity of a Datomic entity to a service or API.
Suppose I have a REST API endpoint
/api/post/<id>
where <id> identifies some blog post (a blog post entity).
With a relational database backend I might have <id> be of some serial integer type stored in a column named id in a table named post.
Since Datomic doesn’t have tables (entities) in the same sense, and its entity IDs are unique database-wide I wonder how this is usually done with Datomic?
Should the entity identifier be exposed directly? According to the documentation an entity identifier is database-unique, so that would work. But the documentation doesn’t specify what the type of an entity identifier is, so perhaps not. (If it is a java.lang.Long can it be negative?)
Or should a UUID or squuid attribute (:post/id) be exposed instead? Further down in the same documentation it says ‘It is often important to have a globally unique identifier for an entity. Where such identifiers do not already exist in the domain, you can use a unique identity attribute with a value type of :db.type/uuid’. Is that it? Is it generally required to add an attribute like :post/id to all such entities?

Unless the endpoint is ephemeral, you should really not expose the entity number (see here for detailed reasons), so using the value of an identity attribute is a good way to go about this. This attribute can be of type UUID indeed, but Strings or numbers can work too.
With Datomic, you also have the opportunity to use "self-contained" identifiers, e.g Datomic lookup refs ([:post/id "fdslkjfdskjfsl"] instead of just "fdslkjfdskjfsl"). This comes in handy to make your route less specific than being about posts. Because of Datomic's schema flexibility (compared to say SQL tables or MongoDB collections), this benefit is especially easy to achieve. You could implement this e.g by edn-encoding the lookup ref in the URL.

Related

Are global non-transaction queries strongly consistent on Cloud Firestore in Datastore Mode?

The following docs page claims:
Eventual consistency: Datastore queries become strongly consistent
unless you explicitly request eventual consistency.
https://cloud.google.com/datastore/docs/firestore-or-datastore#in_datastore_mode
But the following docs page seems to say that maybe global non-transactional queries are not strongly consistent:
The non-transactional read consistency to use. Cannot be set to STRONG
for global queries.
https://cloud.google.com/datastore/docs/reference/data/rpc/google.datastore.v1#readoptions
What's the correct way to understand this? For example, is an entity is deleted outside a transaction, is it possible for a separate non-transactional query to return that entity afterwards?
Looks like the docs could use an update, from your second link "For Cloud Firestore in Datastore mode, if read_consistency is not specified then lookups and all queries default to read_consistency=STRONG.". Queries are strongly consistent for Firestore in Datastore mode unless explicitly requested otherwise.
So if you delete an entity, then start a query that would have matched the deleted entity, the entity will not be returned.

setting foreign key and primary key in gcp firestore

I am new to GCP and NOSQL.
is it possible to have primary and foreign key in the GCP fire-store
Example: I have two table STUDENT and DEPARTMENT
table looks like below
Department-table
dept-id(primary key)
deptname
Student-table
dept-id(foreign key)
student-id
student name
can anybody please help in design this in GCP Fire-store?
To a database, a key is the same as any UUID/randomID and can be shared and used between users, teams, admins, businesses, of all kinds. what matters is how that data is associated. Since Firestore is a noSQL database, there is no direct relational references, so one key cannot be equal to another without including secondary lookups.
In the same way you would define a user profile by an ID, you can create an empty document with a random ID to facilitate the ID of a team, or in this case the department. You can also utilize string combinations if you have a team and a sub-team, so long as at the point of the database request you have access to the team/department ID, you can use Regex to match a string comparison.
Example: request.resource.data.name.matches('/^' + departmentID)
To make a foreign key work with Security Rules or within the client, you must get the key that contains the data as the key should be the name of the document in question to streamline the request as you cannot perform queries or loop through data within Security Rules.
I great read on this subject, I highly suggest this article
https://medium.com/firebase-developers/a-list-of-firebase-firestore-security-rules-for-your-project-fe46cfaf8b2a
But my suggestion is to use a key that represents the department directly rather than using additional resource to have a foreign key and managing it.
Firestore won't support referential integrity.
It means that you can use any (subject to rules and conventions) names for fields, but the semantic and additional functionality is to be maintained by you, rather than by the system.

Loopback default values for missing properties when fetching data from MongoDB

How should I define the Loopback model so that all the properties listed in the model JSON file would always appear on the result even when those properties have no value (or are missing) from the MongoDB record? Should this behaviour be configured in the Loopback or in the MongoDB?
Thanks!
MongoDB is a Schema-less database. It is designed in this way to give us flexibility for adding new fields to a document without any need to restart the database. So I don't think that it is a good idea to handle this scenario on the database side.
I think the best way to handle this could be setting a default value for every property in LoopBack model definition. This solution has a problem when some data is inserted into the database from outside the project.
You can also handle missing parameter at the front-end side.
Another solution that I can think of, is implementing an afterRemote method for checking the existence of all the fields. In this case, you can use this function after any API route that you want to. You can check the following link for more information:
https://loopback.io/doc/en/lb3/Remote-hooks.html#signature

Create a doctrine repository class without an entity

I'm currently in a situation where I need to create a Repository class which would contain multiple financial statistic queries. The queries are not exactly tied up with one Entity but rather with multiple Entities and will select specific data from the database, based on various some conditions.
Having said that, I'm looking for a way to create a Repository class (i.e. StatisticsRepository) which is not associated with an Entity at all, so I could store the queries there. Simply creating that repository doesn't seem to be working. I'm guessing I probably need to create a service of some kind that loads this repo class? Is this correct, and if so is there an example I'm missing in the Symfony/Doctrine docs?
You can just create a class like StatisticsService/StatisticsFinder (naming convention is for you).
That service should have an entity manager injected, so define it in your config.
Create a query builder inside that service, then simply get and return results.

designing api using row ids in request and response

is it a good practice to give row ids in api response and using row ids in api request queries.
whether to use uniquely generated key instead of row ids for api.
Are there any security issues in using row ids
It is commonplace for returned entities to have a unique identifier attached to them. This is typically, but not always, the same as a unique database identifier. If exposing the unique database id is a security issue, it's almost always because an attacker is able to write SQL to your database. In that case, you're better served patching the SQL vulnerability, since the attacker can trivially get unique ids in that case anyway.
There is a good argument for using non-linear ids, as it prevents an attacker from walking through all your data looking for parts of the API you forgot to secure.