Reputation: 101
I have a node application where I am using rethinkdb as database. The id rethinkdb generates for each document is not human readable and not suitable for real world reference purpose.
For example, each user I create I want to have a short integer id which I can use to refer that user in real world. The id I get from database is not suitable for that.
What would be a concurrent safe way to generate a short unique integer id ?
Upvotes: 2
Views: 551
Reputation: 5986
Building off of @Suvitruf 's answer you can accomplish this in pure reql using the following where "last" is a table that contains the last id. Modifications made here are specifically for parallel updates. Instead of individual id updates for each update, the number block is reserved in 1 insert that is part of the query. Please award any points to his answer.
r([{ foo: 'a' }, { foo: 'b'}])
.do(records => {
return r.table('lastId').get('last')('current')
.do(current => {
return r.table('lastId').get('last').update({ current: current.add(records.count()) })
.do(() => {
return r.range(0, records.count()).map(idx => {
return records.nth(idx).merge(rec => {
return { id: current.add(idx) }
})
})
})
})
})
.coerceTo('array')
.do(records => {
return r.table('ids').insert(records)
})
Upvotes: 1
Reputation: 5672
You can create new table, for example, System.
Add to this table just one record:
{
id: "myLastId",
current: 0
}
When you want to insert new record to another table, you need to increment this id first and return it:
const getNewId = r.table("System").get("myLastId").update({
current: r.row("current").add(1)
},
{returnChanges: true});
Your new id will be in result.changes[0]["new_val"].current
. Now, you can insert new record with this id.
Yes, you have to send additional request each time you want to insert new record, but, at least, this method is 100% atomic and synchronized between all nodes in cluster.
Upvotes: 0