Auto increment in Rethinkdb - rethinkdb

Does RethinkDb support AUTO_INCREMENT on a integer column similar to AUTO_INCREMENT in Mysql. https://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html

No, RethinkDB doesn't support it. The reason is because of its distribution. It's hard to have an auto increment number on such that environment because you have to check on multiple machines for next incremental value.
Now, let's think what problem auto increment solve? On MySQL, We want to use it for primary key so it needs to be unique. That's all about it. Auto increment doesn't give you anything else.
In RethinkDB, UUID guarantees the uniqueness, especially in the case of primary key.
Auto Increment is also predictable, probably it isn't cause any harmful but ideally, it gives people a sense of what's next value to attack. For example, take a poor design application, where we can visit some URL like /this/is/a/sensitive/part/123, someone can hit /this/is/a/sensitive/part/124. Of course, this is the fault of application for not having a solid authentication system. However, UUID may help reduce this a bit because UUID isn't predictable.

we archive like below example
```
r.db('autoInc').table('testauto')
.insert(r.do(function() {
return {
autoVal:r.branch(
r.db('FlowzEngine').table('task_worker').isEmpty().not()
.and(r.db('FlowzEngine').
table('task_worker').hasFields('autoVal')
.isEmpty().not()),
r.db('FlowzEngine').table('task_worker')
.hasFields('autoVal').max('autoVal')
.do(function(doc){
return doc('autoVal').add(1)
}),
1)}
}))
```

you can achieve this using a counter table like below:
r.table('counters')
.get(id)
.update({
count: r.row('count')
.default(0)
.add(1)
}).run(conn, callback);

An example based on Chirag's answer, for php, if using Daniel Mewes php-rql..
Chirag's answer for some reason is showing using separate tables, this isn't required, not sure if it's an oversight in the example or not..
$result = \r\table('user')
->insert(array(
'username' => $username, /* other data for example */
'password' => $password,
'userId' =>
\r\rDo(null, function($arg) {
return \r\branch(
\r\table('user') /* if */
->isEmpty()->not()
->rAnd(
\r\table('user')
->hasFields('userId')
->isEmpty()->not()
),
\r\table('user') /* then */
->hasFields('userId')
->max('userId')
->rDo(function($arg) {
return $arg('userId')->add(1);
}),
1); /* else */
})
))
->run($db);
I thought I would add it as it took me more than a few minutes to get this working on PHP, syntactical differences can be annoying.

Related

Quickly accessing variables between clients in Socket.IO

(I'm asking and answering this question because I think it might be useful, but if anything here is flawed let me know.)
Setting and getting custom variables in Socket.IO's socket object is super convenient for ephemeral data you want to associate with that connection.
In the chatroom example, (in this instance I'm using PHP but it should be readily translatable) the script stores user names there:
$socket->on('add user', function ($username) use ($socket) {
$socket->username = $username;
Which you can then use in your broadcast:
$socket->broadcast->emit('user joined', array(
'username' => $socket->username,
'numUsers' => $numUsers
));
The question I've had is how to 'share' the variable data between sockets (connections) without (or before) emitting it? This would be useful for managing more complex chatrooms, or something like a game where you may want to work with this data and not emit.
There are approaches I can think of that could do the job, such as managing distinct arrays, or storing and retrieving with a database -- but they seem redundant if you don't explicitly need to do so.
I wasn't able to find much documentation on this.
Sticking with the chatroom example, this is what I came up with:
Let's say you want to set and get the age of everyone in a particular room:
$socket->on('add user', function ($username,$age) use ($socket) {
$socket->age = $age;
I made a function to collect the unique connection id's of everyone who's in a room:
function clients_in_the_room($room)
{
GLOBAL $io;
$clients_in_the_room = $io->sockets->adapter->rooms[$room];
$clients_in_the_room = array_keys($clients_in_the_room);
return $clients_in_the_room;
}
$io->sockets->adapter->rooms[$room]; is just going to give us an array with booleans, so I've caught the array_keys, which are the id's I want, those are very useful.
$clients_in_the_room = clients_in_the_room('Lobby');
Now we have those id's, we can access those socket variables I wanted:
function socket_age($socketid) {
GLOBAL $io;
$age = $io->sockets->connected[$socketid]->age;
return $age;
}
Beautiful. For clarity, I could emit all this data...
foreach($clients_in_the_room as $clientsId) {
$age = socket_age($clientsId);
$output = "Connection ID: $clientsId Age: $age.";
$socket->broadcast->emit('new message', array(
'username' => $socket->username,
'message' => $output
));
};
But obviously we don't want to do that usually. It's just super useful to know how to quickly access those variables. Hope this is useful.

Laravel validation: unique with multiple columns and soft_delete

I am trying to do a Laravel validation rules as follow:
"permalink" => "required|unique:posts,permalink,hotel_id,deleted_at,NULL|alpha_dash|max:255",
The explanation to the rules is:
I have a table "Posts" in my system with the following fields (among others): hotel_id, permalink, deleted_at. If MySQL would allow make an unique index with null values, the sql would be:
ALTER TABLE `posts`
ADD UNIQUE `unique_index`(`hotel_id`, `permalink`, `deleted_at`);
So: I just add a new row IF: the combination of hotel_id, permalink and deleted_atfield (witch must be NULL) are unique.
If there is already a row where the permalink and hotel_id field are the same and 'deleted_at' field is NULL, the validation would return FALSE and the row wouldnt be inserted in the database.
Well. I don't know why, but the query Laravel is building looks like:
SELECT count(*) AS AGGREGATE FROM `posts`
WHERE `hotel_id` = the-permalink-value AND `NULL` <> deleted_at)
What the heck...
The query I was hoping Laravel build to validation is:
SELECT count(*) AS AGGREGATE FROM `posts`
WHERE `permalink` = 'the-permalink-value' AND `hotel_id` = ? AND `deleted_at` IS NULL
Could someone explain me how this effectively works? Because everywhere I look it looks like this:
$rules = array(
'field_to_validate' =>
'unique:table_name,field,anotherField,aFieldDifferentThanNull,NULL',
);
Does anyone could help me?
Thank you
all.
Finally, I got a proper understanding of the validation (at least, I think so), and I have a solution that, if it is not beautiful, it can helps someone.
My problem, as I said before, was validate if a certain column (permalink) is unique ONLY IF other columns values had some specific values. The problem is the way Laravel validation string rules works. Lets get to it:
First I wrote this:
"permalink" => "required|unique:posts,permalink,hotel_id,deleted_at,NULL|alpha_dash|max:255",
And it was generating bad queries. Now look at this:
'column_to_validate' => 'unique:table_name,column_to_validate,id_to_ignore,other_column,value,other_column_2,value_2,other_column_N,value_N',
So. The unique string has 3 parameters at first:
1) The table name of the validation
2) The name of the column to validate the unique value
3) The ID of the column you want to avoid (in case you are editing a row, not creating a new one).
After this point, all you have to do is put the other columns in sequence like "key,value" to use in your unique rule.
Oh, easy, an? Not so quickly, paw. If you're using a STATIC array, how the heck you will get your "currently" ID to avoid? Because $rules array in Laravel Model is a static array. So, I had to came up with this:
public static function getPermalinkValidationStr() {
$all = Input::all();
# If you are just building the frozenNode page, just a simple validation string to the permalink field:
if(!array_key_exists('hotel', $all)) {
return 'required|alpha_dash|max:255';
}
/* Now the game got real: are you saving a new record or editing a field?
If it is new, use 'NULL', otherwise, use the current id to edit a row.
*/
$hasId = isset($all['id']) ? $all['id'] : 'NULL';
# Also, check if the new record with the same permalink belongs to the same hotel and the 'deleted_at' field is NULL:
$result = 'required|alpha_dash|max:255|unique:posts,permalink,' . $hasId . ',id,hotel_id,' . $all['hotel'] . ',deleted_at,NULL';
return $result;
}
And, in the FrozenNode rules configuration:
'rules' => array(
'hotel_id' => 'required',
'permalink' => Post::getPermalinkValidationStr()
),
Well. I dont know if there is a easiest way of doing this (or a much better approach). If you know something wrong on this solution, please, make a comment, I will be glad to hear a better solution. I already tried Ardent and Observer but I had some problems with FrozenNode Administrator.
Thank you.

Rethinkdb: Know which records were updated

Is there any way to update a sequence and know the primary keys of the updated documents?
table.filter({some:"value"}).update({something:"else"})
Then know the primary keys of the records that were updated without needing a second query?
It's currently not possible to return multiple values with {returnVals: true}, see for example https://github.com/rethinkdb/rethinkdb/issues/1382
There's is however a way to trick the system with forEach
r.db('test').table('test').filter({some: "value"}).forEach(function(doc) {
return r.db('test').table('test').get(doc('id')).update({something: "else"}, {returnVals: true}).do(function(result) {
return {generated_keys: [result("new_val")]}
})
})("generated_keys")
While it works, it's really really hack-ish. Hopefully with array limits, returnVals will soon be available for range writes.

Laravel 4: making a combination of values/columns unique

I'm importing a bunch of csv entries in my database with Laravel 4.
I can't really point at one column that has to be unique, it's a combination of 5 columns that makes it unique. However: how does one define this in Laravel?
Option 1: schema builder
You can use the $table->unique('email') method, but that only seems to allow one column, not a combination of columns.
Option 2: Validation
Less preferable, but I could validate the model before inserting it. However, again, using 'unique:[table]' validation rules, it will return an error when just one of the column values isn't unique, not a combination of them.
Can anyone tell me how I should go about this?
I'm sure I'm missing something, but I could use a push in the right direction :-)
Thanks,
Dieter
You can combine:
$table->unique( array('email','name') );
And pretty much everything in Laravel will accept arrays to do whatever you need to with 'more than one'.
Use Schema Builder's unique() method to define your data model, as Antonio mentioned.
Additionally, if you want to use validation on your model, consider my custom Validator rule for multiple UNIQUE indexes: https://github.com/felixkiss/uniquewith-validator
You can also do this;
$table->unique(["column1", "column2"], 'uq_columns');
Which means that you will have a unique column combination of all the columns i.e. column1 and column2
I know this question is for Laravel 4, but I just came across this on searches and found a solution for Laravel >= 5.3
Here it is:
Of course, the migration may look something like
$table->unique( array('email','name') );
Then to validate this, you do not need to use custom rules, just advanced rules:
'email' => Rule::unique('users')->where(function ($query) use ($request) {
return $query->where('name', $request->name);
}),
Of course, you may want to validate name before of this. The name should be required so that you may finish with something like this:
'name' => 'required|max:255',
'email' => Rule::unique('users')->where(function ($query) use ($request) {
return $query->where('name', $request->name);
}),
I hope it helps.
You can try this
$table->string("name");
$table->string("email")->unique("name")

db active records

I'm trying to get some data from my database with active records,and I'm having the following problem. I wanna learn how to do it with active records since after this code i have a ton of joins and other stuff. Otherwise I would write a normal query.
$this->db->where("sa.country", $country);
// I NEED TO OPEN BRACKETS HERE SO THAT I CAN GET THE LANGUAGES IF THERE IS DATA IN ONE OF THE ARRAYS
if (isset($lid[0]))$this->db->where("sa.lang", $lid[0]);
if (isset($lid[1]))$this->db->or_where("sa.lang", $lid[1]);
if (isset($lid[2]))$this->db->or_where("sa.lang", $lid[2]);
if (isset($lid[3]))$this->db->or_where("sa.lang", $lid[3]);
if (isset($lid[4]))$this->db->or_where("sa.lang", $lid[4]);
//AND CLOSE THEM HERE
My goal is to get a specific country from db, with the corresponding languages that are in the arrays.
I think you should use WHERE...IN...! See help about 'where in'.
With ActiveRecord:
$this->db->where_in("sa.lang",$lid);
Does this help?
$this->db->where("sa.country", $country);
// loop through *set* languages
foreach($lid as $item)
{
$this->db->where('sa.lang', $item);
}
// will return a query object
return $this->db->get('my_table');
Here is how I solved the problem for anyone interested in the solution.
$this->db->where("(`sa`.`lang` = '$lid[0]' OR `sa`.`lang` = '$lid[1]' OR `sa`.`lang` = '$lid[2]' OR `sa`.`lang` = '$lid[3]' OR `sa`.`lang` = '$lid[4]')");

Resources