in keystoneJs's doc:
Populating related data in queries
You can populate related data for relationship fields thanks to Mongoose's populate functionality. To populate the author and category documents when loading a Post from the example above, you would do this:
Post.model.findOne().populate('author categories').exec(function(err,post) {
// the author is a fully populated User document
console.log(post.author.name);
});
my question is that there is any options I can configure so these List APIs can populate the many relationship automatically.
thanks.
mike so
I think not. This is how I do it when I use Keystone as an API (using .populate).
exports.getStoreWithId = function (req, res) {
Store.model
.find()
.populate('productTags productCategories')
.where('_id', req.params.id)
.exec(function (err, item) {
if (err) return res.apiError('database error', err);
res.apiResponse({
store: item,
});
});
};
Pretty sure the short answer here is no. If you want to populate you'll need to include the .populate.
That being said, keystone gives you access to the mongoose schema, so the answer here should work. Obviously their mongoose.Schema is done by your Post.add stuff so I think you can ignore their first snippet, and you should be able to add the hooks as Post.schema.pre(... for the second snippet.
The Post.schema.pre('save',... hooks definitely work with keystone, so I assume the pre-find hooks work too, however I've not actually tested this. (I'd be interested to know the outcome though!)
Finally, if that works, you could also have a look at the mongoose-autopopulate package, and see if you can get that to play nicely with keystone.
Related
I built my own simple REST API with Express and now I'm consuming it from my client (Vue.js)
So in my page I access all the data from this endpoint: GET /api/books, and it works fine
Now I also have a "sort by" button where I want to get the data by the latest entries. I don't know if that's a good way or if I have to handle this in the backend but what I do is calling the same endpoint which is GET /api/books and sorting the data to get them the right way
For ex:
sortByLatest() {
axios
.get("/api/books")
.then(res => {
const books = res.data;
const sortedBooks = books.sort((a, b) => b.createdAt > a.createdAt ? 1 : -1
);
this.books = sortedBooks;
})
// catch block
}
I do that for everything. If I need a limited number of results or a specific property from the data I have to write some logic in the axios .then block to sort or filter what I want. Is this bad practice?
But that's not my actual problem
My problem is, in addition of sorting by the latest entries, I also want to filter the results by a specific property. The problem is when I click the A button it's gonna filter the books by a specific property, and when I click the B button it's gonna sort them buy the latest entries, but not both at the same time!
And what if I want additionnal things like limit the number of results to 10, filter by other properties etc... I want to be able to create requests that ask all those things at once. How can I do that? Do I have to build that in the backend?
I saw some websites using url parameters to filter stuff, like /genre=horror&sort=latest, is that the key of doing it?
Thank you for your time
Using NodeJS, I am trying to update relationship field which link to another app (contacts-leads). I have try all combination but still getting error. I think I have the necessary data to post, app_id, item_id, external_id..etc. I need help with forming JSON structure.
p.request('put','item/<Item_Id>/value', data)
var data {....}
app_id:'<app_id>'
value:'<value>' (value is the app_item_id of the link to application; that is the number in URL)
app_item_id: '<app_item_id>'
external_id:'<external_id>'
I was able to update non-relationship field without problem.
Thanks
Well, going to answer my own question. That will work for single app link, not sure about multiple ones.
data = {
"<external_id>": {
"apps": [{"app_id": <app_id>}],
"value: <app_item_id>
}
}
I've read the docs and I understand that I'm not passing an instance of the schema and checked around stackoverflow for duplicates and I did not find an adequate example explaining the differences, use cases and pros and cons for both.
I've been using both these methods almost interchangeably to access a model in a controller file and so I'm wondering what is the difference under the hood between both and what is generally "best practice". It seems more convenient to use mongoose.model() when you are in a heavily nested file structure but i noticed it errors out when there is no data stored in the collection. Here is an example using both methods that works fine as far as I can tell.
var Slideshow = require('../models/mongoose/Slideshow');
var Events = mongoose.model('Events');
Slideshow.find(function (err, slides) {
Events.find(function (err, events) {
res.render('demo', {
slideshow : slides,
events : events
});
});
});
If I understand the first correctly, it's just using require to get the user.js mongoose model which defines the schema eventually runs var User = module.exports = mongoose.model('User', UserSchema); where as the second is directly calling mongoose and asking for the model. But aside from that is there any performance differences or use case differences? Is there anything I missed?
What is the right way to updated the Model in the view, say after a successful API POST. I've a textarea, something like in a Twitter, where a user can enter text and post. The entered text must show up soon after it is posted successfully.
How to achieve this? Should I make another call to get the posts separately or is there any other way to do this?
My Code looks like
feedsResolve.getFeeds().then(function(feeds){
$scope.feeds = feeds;
}
where feedsResolve is a service returning a promise
$scope.postFeed = function(){
var postObj = Restangular.all('posts');
postObj.post( $scope.feed.text ).then(function(res){
//res contains only the new feed id
})
}
How do I update the $scope.feeds in the view?
I assume you are posting a new post and that generally posts look like:
{
id: 42,
text: 'This is my text'
}
In this case you can do something like:
$scope.postFeed = function(){
var postObj = Restangular.all('posts');
var feedText = $scope.feed.text;
postObj.post( feedText ).then(function(res){
$scope.feeds.push({ id: res.id, text: feedText});
})
};
A better practice when writing restful service though is to just have your POST return an actual JSON object with the new feed that was added (not just the id). If that were the case you could just add it to your feeds array.
If your JSON object is complex, this practice is the most common an easiest way to handle this without needing extra requests to the server. Since you already are on the server, and you've likely already created the object (in order to be able to insert it into the database), all you have to do is serialize it back out to the HTTP response. This adds little to no overhead and gives the client all the information it needs to effortlessly update.
I use datatables on the client to allow speedy live sorting/filtering of around 10,000 rows of data. It is much faster to supply an array of rows to a DataTable during table creation than to add the rows individually. I can use the onReady function in subscribe to achieve this.
If I then call observe to pick up changes, I get the data already supplied in subscribe again.
While I can hack around this, I presume I am just not using meteor correctly and appreciate any advice.
Here is some sample code:
Meteor.subscribe("books", function(){
// Runs when subscription is complete
var mData = Books.find().fetch();
MyTable = $('#testTable').dataTable( {
'aoColumns': [
{ sTitle: 'title', sClass: 'alignRight', mDataProp: 'title'},
],
'aaData' : mData
});
// Add any new books.
Books.find().observe({added: function(item){
// ERR: Adds the books already fetched into mData as well as any new books.
MyTable.fnAddData([item]);
}});
});
There's a hidden option to observe ({_suppress_initial: true}) that avoids this behaviour. I'm not sure if it's a good idea to use it, but it is there.
As for advice around how to structure your code; it's not as easy as it should be, but I think you want to something like the following:
Wrap your table in a {{#constant}} helper so it never gets re-rendered.
Make sure the table doesn't get rendered the one-and-only time until the data is ready (this could help: https://github.com/oortcloud/unofficial-meteor-faq#how-do-i-know-when-my-subscription-is-ready-and-not-still-loading)
Do your code above in the table's Template.table.rendered callback.
That approach seems more modular.