I have a local server that I have created to learn and practice my backend coding. Right now its in the early stages of becoming a "netflix" style app. I have a code:
app.get("/movies/:title", (req, res) => {
res.json(movies.find((movie) => {
return movie.title === req.params.title
}));
});
that when I type this URL: localhost:8080/movies/:title (insert title name) it returns the desired movie form this array:
let movies = [
//1
{
title: 'Lord of the Rings',
actor: 'Orlando',
genre: 'adventure',
director: 'person'
} ,
//2
{
title: 'Harry Potter',
actor: 'Daniel Radcliffe',
genre: 'Fantasy',
director: 'person',
Movie_ID: "7"
} ,
//3
{
title: 'Imaginaerum',
actor: 'Toumas Holopainen',
genre: 'Fiction',
director: 'person',
Movie_ID: "1"
} ,
//4
{
title: 'Cloud Atlas',
actor: 'Person',
genre: 'Fantasy',
director: 'person'
}
However, when I try to do the same, but with the key value "actor" in this URL:
localhost:8080/movies/:actor (replace for actor name)
nothing shows up. Here is the code for that:
app.get("/movies/:actor", (req, res) => {
console.log(req.params)
res.json(movies.find(movie => {
return movie.actor === req.params.actor
}));
});
All help is greatly appreciated!
As #Đăng Khoa Đinh explained, these are the same routes, so your code doesn't know which end point to use.
Change one to:
/movies/actor/:actor/ and the other to /movies/title/:title or a similar change to get this working.
Related
So first I have a query that finds books that has been borrowed by user, it will search using the Borrow model
const bookqueryinitial = await Borrow.find({borrower_Id : String(_id), borrowStatus: req.query.status}).sort({"borrowDate": -1 }).skip(skip).limit(pageSize);
it will return results like this
[
{
_id: new ObjectId("628ebcc10944a1223397b057"),
borrower_Id: '6278d1b6b4b7659470572e19',
borrowedbook_Id: '62710ac63ad1bfc6d1703162',
borrowStatus: 'pending',
borrowDate: 2022-05-25T23:33:21.849Z,
__v: 0
},
{
_id: new ObjectId("628d9c0b9a3dc72f4aa72f1a"),
borrower_Id: '6278d1b6b4b7659470572e19',
borrowedbook_Id: '62710ac63ad1bfc6d170314d',
borrowStatus: 'pending',
borrowDate: 2022-05-25T03:01:31.416Z,
__v: 0
}
]
next is I will map through the borrowedbook_Ids of the result and store them in an array
const booksinsidequery = bookqueryinitial.map(bookids=>{
return bookids.borrowedbook_Id
})
then I will search the ids that is stored in array and search for those ids in the Book model
const bookquery = await Book.find({ '_id': { $in: booksinsidequery } });
\\and the result is somethign like this
[
{
_id: new ObjectId("62710ac63ad1bfc6d170314d"),
title: "Girl who kicked the Hornet's Nest",
author: 'Larsson, Steig',
genre: [ 'fiction' ],
publisher: '',
dateOfPublication: 2017-10-25T00:00:00.000Z,
noOfCopies: 14,
type: 'Article',
form: 'Fiction',
isbn: '978-69793-4824559-56755-9',
dateAdded: 2003-04-23T00:00:00.000Z,
noOfBookmarks: [ [Object] ],
noOfLikes: [],
},
{
_id: new ObjectId("62710ac63ad1bfc6d1703162"),
title: 'We the Nation',
author: 'Palkhivala',
genre: [ 'philosophy' ],
publisher: '',
dateOfPublication: 2011-11-22T00:00:00.000Z,
noOfCopies: 94,
type: 'Book',
form: 'Non-fiction',
isbn: '978-65685-4156343-802140-8',
dateAdded: 2010-06-08T00:00:00.000Z,
noOfLikes: [],
noOfBookmarks: []
}
]
Now before sending the result of the query to the client side, I want to bind my initial queries from Borrow model to my Book model and the final result should be like this
[
{
_id: new ObjectId("62710ac63ad1bfc6d170314d"),
title: "Girl who kicked the Hornet's Nest",
author: 'Larsson, Steig',
genre: [ 'fiction' ],
publisher: '',
dateOfPublication: 2017-10-25T00:00:00.000Z,
noOfCopies: 14,
type: 'Article',
form: 'Fiction',
isbn: '978-69793-4824559-56755-9',
dateAdded: 2003-04-23T00:00:00.000Z,
noOfBookmarks: [ [Object] ],
noOfLikes: [],
//added properties based on matched condition (Borrow.borrowedbook_Id === Book._id)
borrowStatus: 'pending',
borrowDate: 2022-05-25T03:01:31.416Z,
},
{
_id: new ObjectId("62710ac63ad1bfc6d1703162"),
title: 'We the Nation',
author: 'Palkhivala',
genre: [ 'philosophy' ],
publisher: '',
dateOfPublication: 2011-11-22T00:00:00.000Z,
noOfCopies: 94,
type: 'Book',
form: 'Non-fiction',
isbn: '978-65685-4156343-802140-8',
dateAdded: 2010-06-08T00:00:00.000Z,
noOfLikes: [],
noOfBookmarks: [],
//added properties based on matched condition (Borrow.borrowedbook_Id === Book._id)
borrowStatus: 'pending',
borrowDate: 2022-05-25T23:33:21.849Z,
}
]
How can I attain these results?
You can achieve this with the aggregation framework that MongoDB provides.
Based on your data here is an example: https://mongoplayground.net/p/DQJIbcqBDKM
Lookup : the operator helps you to join data between different collections and the matched data will be in an array. In this case, called borrows
Unwind : will create a document per item on a specified array
Addfields : Allows you to create new attributes, in this case, the two that you wanted "borrowStatus" and "borrowDate"
Project : this operator allows you to hide or show data in the next stage. In this case, 0 means that we will hide a specific attribute
//Array of books
const books = [{
title: 'The subtle art of not giving a fuck',
author: 'Mark Manson'
},{
title: 'Everything is fucked',
author: 'Mark Manson'
},{
title: 'Seriousness takes the joyfulness of life',
author: 'Karan Siddannavar'
}]
const getBooks = book => {
document.querySelector('.book-list').innerHTML = `<li>${book.title}</li>
<li>${book.author}</li>`
}
books.forEach(book => {
getBooks(book);
})
<div class="book-list"></div>
I call the getBooks method every time the book variable is updated with a new object. But, the function gets called only once. In other words, the details of only one book is displayed, even though the function is called every time the forEach loops through the array. Why does this happen?
In each call of the function you are replacing the innerHTML (previous content with the current content), you have to use += instead of = to retain the previous HTML.
Though, I will suggest you to use Element.insertAdjacentHTML() instead of innerHTML:
const books = [{
title: 'The subtle art of not giving a fuck',
author: 'Mark Manson'
},{
title: 'Everything is fucked',
author: 'Mark Manson'
},{
title: 'Seriousness takes the joyfulness of life',
author: 'Karan Siddannavar'
}]
const getBooks = book => {
document.querySelector('.book-list').insertAdjacentHTML('beforeend', `<li>${book.title}</li>
<li>${book.author}</li>`)
}
books.forEach(book => {
getBooks(book);
})
<div class="book-list"></div>
You could use map method instead of forEach and first create content then add it to DOM so you don't have to access DOM in each iteration.
const books = [{
title: 'The subtle art of not giving a fuck',
author: 'Mark Manson'
}, {
title: 'Everything is fucked',
author: 'Mark Manson'
}, {
title: 'Seriousness takes the joyfulness of life',
author: 'Karan Siddannavar'
}]
const getBooks = ({title, author}) => `<li>${title}</li><li>${author}</li>`
const content = books.map(getBooks).join('');
document.querySelector('.book-list').innerHTML = content;
<div class="book-list"></div>
Below is my JSON array and I want to find if contact array has specific value or not.
data = [ { _id: 5a67294923aba20014e2fe5a,
customerLocation: '473 Victoria St, Singapore 198371',
customerName: 'UNIVERSAL',
id: 'UNI3L2',
customerType: 'customer',
contact:
[ 'Brian spilak',
'Brian spilak2',
'Brian spilak3',
'Brian spilak4',
'Brian spilak5' ] } ];
JAVASCRIPT
function findContact(data,con){
return data.contact.find(item => {
return item.data.contact == con;
})
}
console.log('Contact Name :', findContact(data,'Brian spilak2'));
item doesn't have data.contact property and your data response it an array, so you have to specify an index do work with:
function findContact(data,con){
return data[0].contact.find(item => {
return item == con;
})
}
You can use data.contact for contact data shown
You can use array#find with array#includes to check if a name exists in the contact property of the object.
var data = [ { _id: '5a67294923aba20014e2fe5a', customerLocation: '473 Victoria St, Singapore 198371', customerName: 'UNIVERSAL', id: 'UNI3L2', customerType: 'customer', contact: [ 'Brian spilak', 'Brian spilak2', 'Brian spilak3', 'Brian spilak4', 'Brian spilak5'] } ];
var result = data.find(o => o.contact.includes('Brian spilak2'));
console.log(result);
This one returns all the objects matching the name criteria in the array.
function filterName(data, srchName) {
return data.filter((obj) => {
return obj.contact.indexOf(srchName) !== -1
})
}
console.log(filterName(data, 'Brian spilak'));
Use indexOf.Since it is only one object data[0] is used to get the first object, if it is an array of object you can use forEach method
var data = [{
_id: '5a67294923aba20014e2fe5a',
customerLocation: '473 Victoria St, Singapore 198371',
customerName: 'UNIVERSAL',
id: 'UNI3L2',
customerType: 'customer',
contact: ['Brian spilak',
'Brian spilak2',
'Brian spilak3',
'Brian spilak4',
'Brian spilak5'
]
}];
function findContact(data, con) {
if (data[0].contact.indexOf(con) !== -1) {
return 'found';
} else {
return 'not found';
}
}
console.log('Contact Name :', findContact(data, 'Brian spilak2'));
I have a problem with populate. I made a query to get User, Project and Topic information (Those are my 3 models). I need to show multiples dates in profile view. This is my code:
Project.js:
module.exports = {
attributes: {
name: {
type: "string"
},
topics: {
collection: "topic",
via: "projects"
},
members: {
collection: "user",
via: "projects"
},
content: {
collection: "content",
via: "projectData"
}
}
};
Topic.js:
module.exports = {
attributes: {
name: {
type: "string"
},
projects: {
collection: "project",
via: "topics"
}
}
};
in User.js:
show: function(req, res, next) {
User.findOne({id: req.session.User.id}).populateAll().exec(function prjFound(err, user){
if (err) return next(err);
if (!user) return next();
console.log(user);
res.view({
user: user
});
});
},
Console print this:
{ projects:
[ { name: 'Fran',
createdAt: '2017-06-19T21:33:17.152Z',
updatedAt: '2017-06-19T21:33:17.190Z',
id: 97 },
{ name: 'River Plate',
createdAt: '2017-06-19T21:36:38.757Z',
updatedAt: '2017-06-19T21:36:38.798Z',
id: 98 },
{ name: 'Guido',
createdAt: '2017-06-20T01:33:53.843Z',
updatedAt: '2017-06-20T01:33:53.926Z',
id: 99 } ],
group: [],
mat: 222222,
name: 'Francisco',
lastname: 'P',
email: 'fran#1.com.ar',
encryptedPassword: '$2a$10$nKp/eAOCDPw4BS.PvQCThe42wa2/8ZABw4JzA0no9GPVT4VjFl3ZO',
createdAt: '2017-06-19T21:32:10.535Z',
updatedAt: '2017-06-19T21:32:10.535Z',
id: '594842da6aeecd880ebab4e6'
}
I want to get all atributes of project model (Content, topic, and members), not only the name and id.
Anyone can explain Why my code is wrong?
Sails/Waterline populate/populateAll do 1 level of population. For 2 or deeper level you need to write code for it.
E.g. Gather ids of user's project and do populateAll on Project.find
Sailsjs doesn't currently support population within a populated field. Write a query in the returned response and append it to the field that you want to populate, send the response with your desired results.
Check this.
let result = await model.find(filter).populate("fieldName", {select:['attribute1','attribute1']})
I have Mongoose model instance:
var s = new Song({
song_id: '123',
title: 'sample song',
artist: {
name: 'sample artist',
id: '456'
}
});
Now I'd like to set/update its properties but using extend (e.g. from nodejs util._extend)
s = extend(s, {
title: 'changed title',
artist: {
name: 'changed artist',
id: '789'
}
});
s.save();
And while title (as a top-level property) gets set ok, changes in artist are not visible.
I know I can just set it via:
s.artist.name = 'changed artist';
but is there something I'm missing or is this way of updating properties not usable?
EDIT
Gah... Looks like someone defined schema the wrong way. Instead of artist field defined as
artist: {
name: String,
id: String
}
it was defined like
artist.name: String,
artist.id: String
When I redefined it it works now. Thanks
What you can do is to use Mongoose's update method:
Song.update({
song_id: '123',
}, {
$set: {
title: 'changed title',
artist: {
name: 'changed artist',
id: '789',
},
},
}, function(err, numAffected) {
...
});
However, I don't actually see why your extend attempt failed. It seems to work for me, I usually use underscore's _.extend function.