I'm using MongoDB for the first time. I'm used to SQL and didn't shift my thinking to NoSQL yet. This is my model:
var mongoose = require('mongoose');
var website = require('./website');
var plm = require('passport-local-mongoose');
var accountSchema = new mongoose.Schema({
isPremium: Boolean,
websites: [],
});
accountSchema.plugin(plm);
module.exports = mongoose.model('Account', accountSchema);
Now. I know how to add, edit and remove an account
. But I have no clue how to edit the websites
array content. This is an object after registration:
{
_id: ObjectId('5a7fa2af53f3d71dcd28ccb1'),
websites: ['websiteonefree.com', 'websitetwofree.com', 'webs'],
username: 'free@free.com',
isPremium: false,
hash: 'Very long hash',
salt: 'long salt',
__v: 0,
}
The websites are being displayed in a table like this:
<table class="table table-striped table-hover">
<tr>
<th>Url</th>
<% if (user) { %>
<th>Actions</th>
<% } %>
</tr>
<% for(let i=0;i<websites.length;i++){ let website = websites[i] %>
<tr>
<td>
<%= website %>
</td>
<td>
<a href="/websites/<%= website %>" class="btn btn-info">Edit</a>
<a href="/websites/delete/<%= website %>" class="btn btn-danger confirmation">Delete</a>
</td>
</tr>
<% } %>
</table>
Right now the edit function looks like this:
// POST: /websites/_id - save updates
router.post('/:_id', isLoggedIn, function(req, res, next) {
var p = req.params;
var b = req.body;
var website = Website({
_id: p._id,
url: b.url,
});
Website.update(
{
_id: p._id,
},
website,
function(err) {
if (err) {
throwError();
return;
}
res.redirect('/websites');
}
);
});
This works if the websites are a collection of their own. Now I was thinking to do something like, sending the :_id
and website
at the Edit
button click. Then I would query the db, put it into the view and then update it all.
The only problems are:
a) I have no idea how to implement it in code.
b) I'm not sure how to determine the position in the array, which I need to update. Example: websites[0]='a.com'
so how to make sure it updates the right element of the array.
Basically: In SQL
I would just edit it using the foreign key. How do I do it with NoSQL
?
You can do with this the mongoDB aggregation queries https://docs.mongodb.com/manual/reference/operator/update/positional/
Note: Make sure you have compatible version of mongodb
Update all documents in array
db.coll.update({}, {$set: {“a.$[].b”: 2}})
Input: {a: [{b: 0}, {b: 1}]}
Output: {a: [{b: 2}, {b: 2}]}
Update all matching documents in array
db.coll.update({}, {$set: {“a.$[i].b”: 2}}, {arrayFilters: [{“i.b”: 0}]})
Input: {a: [{b: 0}, {b: 1}]}
Output: {a: [{b: 2}, {b: 1}]}
Update all matching scalars in array
db.coll.update({}, {$set: {“a.$[i]”: 2}}, {arrayFilters: [{i: 0}]})
Input: {a: [0, 1]}
Output: {a: [2, 1]}
Update all matching documents in nested array
db.coll.update({}, {$set: {“a.$[i].c.$[j].d”: 2}}, {arrayFilters: [{“i.b”: 0}, {“j.d”: 0}]})
Input: {a: [{b: 0, c: [{d: 0}, {d: 1}]}, {b: 1, c: [{d: 0}, {d: 1}]}]}
Output: {a: [{b: 0, c: [{d: 2}, {d: 1}]}, {b: 1, c: [{d: 0}, {d: 1}]}]}
Update all scalars in array matching a logical predicate
db.coll.update({}, {$set: {“a.$[i]”: 2}}, {arrayFilters: [{$or: [{i: 0}, {i: 3}]}]})
Input: {a: [0, 1, 3]}
Output: {a: [2, 1, 2]}
Each array filter must be a predicate over a document with a single field name. Each array filter must be used in the update expression, and each array filter identifier $[] must have a corresponding array filter. must begin with a lowercase letter and not contain any special characters. There must not be two array filters with the same field name.
I ended up using findById
and save
.
The add POST
method looks like this.
// POST handler for add to process the form
router.post('/add', isLoggedIn, function(req, res, next) {
var user = req.user;
var websites = user.websites;
var filledWebsites = findFilledWebsites(user);
console.log(websites);
if (
(user.isPremium == true && filledWebsites.length < 5) ||
(user.isPremium == false && filledWebsites.length < 3)
) {
let freeIndexes = [];
for (let i = 0; i < websites.length; i++) {
if (websites[i] == '') {
freeIndexes.push(i);
}
}
Account.findById(req.user._id, function(err, acc) {
if (err) {
console.log(err);
} else {
acc.websites.set(freeIndexes[0], req.body.url);
acc.save((err, webs) => {
if (err) {
console.log(err);
} else {
console.log('Website Added');
res.redirect('/websites');
}
});
}
});
} else {
console.log('failed');
res.redirect('/websites');
}
});
Here's the findFilledWebsites
method:
function findFilledWebsites(acc) {
var filledWebsites = [];
for (let i = 0; i < acc.websites.length; i++) {
if (acc.websites[i] != '') {
filledWebsites.push(acc.websites[i]);
}
}
return filledWebsites;
}
The add method can be easily edited to do the rest of the CRUD operations. In this case they are all updating, because empty records are filtered in the view.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.