Short answer
If your goal is to make your code as good looking as possible, I would recommend you use lodash-id, and its updateById
function. I introduce all kind of possible solutions in my long answer, but personally I would avoid chaining directly, and instead do something like:
const lodashId = require('lodash-id');
const low = require('lowdb');
const FileSync = require('lowdb/adapters/FileSync');
const adapter = new FileSync('db.json');
const db = low(adapter);
db._.mixin(lodashId);
const posts = db.get("posts");
posts.updateById( 1, { title: 'edited title 1' }).commit();
posts.updateById( 2, { title: 'edited title 2' }).commit();
posts.updateById( 3, { title: 'edited title 3' }).commit();
posts.write();
Long answer
There are a few ways to approach this problem, and updateById
is not the only way to do it by far. As a matter of fact, it is also possible to do this in one chain by using the tap
function. Below I introduce a few alternatives.
Can I quickly try those functions in the browser?
Of course! I actually made a Codepen where you can try all of the different possible approaches directly in your browser, just remember to open your browser console to see the test results! Here is the link:
https://codepen.io/jhack_jos/pen/XWNrpqX
How do I call the functions?
All those functions receive an adapter as input. You can call them this way:
const result = testcaseXY(adapter);
1A) tap & find+assign
function testcase1A(adapter)
{
const db = low(adapter);
return db
.get("posts")
.tap( (posts) => _.chain(posts).find({ id: 1 }).assign({ title: 'edited title 1' }).commit())
.tap( (posts) => _.chain(posts).find({ id: 2 }).assign({ title: 'edited title 2' }).commit())
.tap( (posts) => _.chain(posts).find({ id: 3 }).assign({ title: 'edited title 3' }).commit())
.write();
}
What is tap
?
- it's a utility function from lodash
- it does not directly change the database
- it does, however, pass a reference to the object hold to the
interceptor
function (in this example I used an arrow function)
- the reference to the value can be changed, thus affecting the object inside the database
- calling
.write()
on the database makes the changes definitive.
2A) tap & find+set
function testcase2A(adapter)
{
const db = low(adapter);
_.mixin(lodashId);
return db
.get("posts")
.tap( (posts) => _.chain(posts).find({ id: 1 }).set("title", 'edited title 1').commit())
.tap( (posts) => _.chain(posts).find({ id: 2 }).set("title", 'edited title 2').commit())
.tap( (posts) => _.chain(posts).find({ id: 3 }).set("title", 'edited title 3').commit())
.write();
}
What is set
?
- it's a slightly shorter way to do what
.assign
does, but only with one property.
- you may expect
.set
to be faster then .assign
3A) tap & updateById
function testcase3A(adapter)
{
const db = low(adapter);
_.mixin(lodashId);
return db
.get("posts")
.tap( (posts) => _.chain(posts).updateById( 1, { title: 'edited title 1' }).commit())
.tap( (posts) => _.chain(posts).updateById( 2, { title: 'edited title 2' }).commit())
.tap( (posts) => _.chain(posts).updateById( 3, { title: 'edited title 3' }).commit())
.write();
}
What is updateById
?
- it's a function that is exposed by the lodash-id library
- you must first add it to lowdb as a mixin
- to do so you first need to require it with
const lodashId = require('lodash-id')
- then you need to call
db._.mixin(lodashId)
;
- here instead I am calling directly
_.mixin(lodashId)
, because I am directly using lodash inside the tap
function, without going through lowdb
1B) temporary variable & find+assign
function testcase1B(adapter)
{
const db = low(adapter);
const posts = db.get("posts");
posts.find({ id: 1 }).assign({ title: 'edited title 1' }).commit();
posts.find({ id: 2 }).assign({ title: 'edited title 2' }).commit();
posts.find({ id: 3 }).assign({ title: 'edited title 3' }).commit();
return posts.write();
}
As you may see, using a temporary variable here gives us a more compact code, which could be easier to read, debug, and refactor.
2B) temporary variable & find+set
function testcase2B(adapter)
{
const db = low(adapter);
const posts = db.get("posts");
posts.find({ id: 1 }).set("title", 'edited title 1').commit();
posts.find({ id: 2 }).set("title", 'edited title 2').commit();
posts.find({ id: 3 }).set("title", 'edited title 3').commit();
return posts.write();
}
3B) temporary variable & updateById
function testcase3B(adapter)
{
const db = low(adapter);
db._.mixin(lodashId);
const posts = db.get("posts");
posts.updateById( 1, { title: 'edited title 1' }).commit();
posts.updateById( 2, { title: 'edited title 2' }).commit();
posts.updateById( 3, { title: 'edited title 3' }).commit();
return posts.write();
}
Thank you for reading!
I'd be glad to give any further explanation, may you need it.
As a bonus I would add it could be possible to write some clever utility function as a lowdb/lodash mixin in order to enable us to have a shorter syntax and still properly chain. That is, however, probably more than what you were looking for.