I have a collection Files which contain items with a userId. I want a unique array with all userIds in the collection.
Here my first approach (code from here: LINK)
Server Method
'uniqUser': function(){
const distinct = Meteor.wrapAsync(Files.rawCollection().distinct,Files.rawCollection());
const result = distinct('userId');
console.log(result)
return result
}
Client Call
uniqUser(){
Meteor.call('uniqUser', function(err, data) {
console.log(data);
return data;
});
}
the console.log looks good:
but my view show nothing!? also no errors...
uniqUser:
{{#each uniqUser}}
<p>{{this}}</p>
{{/each}}
I have to use meteor-reactive-method LINK:
uniqUser() {
return ReactiveMethod.call("uniqUser");
}
and eveything is fine!
Related
The mongoDB data I am displaying is information i scraped from a website using cheerio. I scrape the data, save it into a mongo collection (called Store), and then display that information in an HTML table using ejs.
Problem:
The first table displays information just fine, with 26 rows of data. The second table, however, displays 26 blank rows and then 25 rows of the data i scraped. Sometimes the roles will be reversed, just depending on which scrape occurs first, so I know it has something to do with when it gets put into the db.
Can someone please explain how I can fix this?
Code:
scrape function (function is exactly the same for second set of data but instead of SUP, it says QA):
var scrapeSUP = function() {
var SUPStoreInfo = [];
return Axios.get("http://example.com").then(function(response){
var $ = cheerio.load(response.data);
$('.row > tbody > tr:contains("SUP")').each(function(i, element){
let SUPResult = {
"environment.SUP": $(element).children().next(),
"store.SUP": $(element).children().next().next(),
"version.SUP": $(element).children().next().next().next()
};
SUPStoreInfo.push(SUPResult);
//make sure Store collection is empty
Store.count({}, function(err, count){
if (count === 0) {
//if empty, add newly scraped data
Store.create(SUPResult, function(err, new){
if (err){
console.log(err);
}
});
} else {
//if Store collection is not empty (has old data), remove all contents
Store.remove({}, function(err, doc) {
if (err) {
console.log(err);
} else {
//once all contents removed, add newly scraped data
Store.create(SUPResult, function(err, new){
if (err){
console.log(err);
}
});
}
})
}
});
});
return SUPStoreInfo;
});
}
please let me know if you need to see other code (html tables, mongoose schema, etc)
I am sending a query to mongoDB using mongoose. The collection is named Step. I want the result of this query to be an array of _id values, one per step. Currently I am getting all of the step objects in their entirety, because req.query isn't defined in this case.
service:
this.getSteps = function() {
return $http({
method: 'GET',
url: '/api/step'
})
.then(function(response) {
return response.data;
});
};
controller:
readStep: function (req, res) {
Step.find(req.query, function(err, result) {
if (err) {
res.status(500).send(err);
}
res.status(200).send(result);
});
}
Set the second parameter of the find query to '_id' to retrieve only the _id of the objects.
Step.find(req.query, '_id', function(err, result) {
This will return data like this:
[{_id: 123}, {_id: 234}]
If you want to get an array of the Step ids on their own, use the javascript map function like so
result = result.map(function(doc) {
return doc._id;
});
which will give you an array like this:
[123, 234]
You'll need to use query.select, something like as shown below:
Step.find(query).select({ "_id": 1}).then(....);
I'm not able to type much because I'm responding from my handheld.
Hope this help!
I'm using a MEAN stack and with Mongoose. Is there a way to query MongoDB with multiple ids to only return those specific IDs in one query e.g. /api/products/5001,5002,5003
Is this possible or would I need to query each product individually or add an additional attribute to the products and query by that.
Update: To clarify as suggested below I've managed to get it partially working using {'_id': { $in: [5001,5002,5003]} however I'm having problems figuring out how to pass the list from the api url to the find function.
Using Express.js for router
router.get('/list/:ids', controller.showByIDs);
exports.showByIDs = function(req, res) {
Product.find({'_id': { $in: [req.params.ids]}}, function (err, product) {
if(err) { return handleError(res, err); }
if(!product) { return res.send(404); }
return res.json(product);
})
};
Then trying /api/products/list/5001 works however /api/products/list/5001,5002 doesn't. I'm not sure if it's a syntax problem in the url or my router code that needs to change or the controller.
You can use the $in operator to query for multiple values at once:
Products.find({_id: {$in: [5001, 5002, 5003]}}, function (err, products) { ... });
On the Express side, you need to use a format for the ids parameter that lets you split it into an array of id values, like you had in your first example:
/api/products/5001,5002,5003
Then in your route handler, you can call the split function on the req.params.ids string to turn it into an array of id values that you can use with $in:
exports.showByIDs = function(req, res) {
var ids = req.params.ids.split(',');
Product.find({'_id': { $in: ids}}, function (err, product) {
if(err) { return handleError(res, err); }
if(!product) { return res.send(404); }
return res.json(product);
})
};
I want to populate fields after mapReduce.
mongoose.connection.db.collection('createdCollectionNameForResults', function(err, collection) {
collection.find({}).populate('ref_field').toArray(function(err, items) {
res.send(200, items)
});
});
But here, it gives error:
TypeError: Object # has no method 'populate'
Because collection.find({}) returns mongodb cursor. How can I populate ref_field?
Considering that you have a Schema registered in mongoose named 'createdCollectionNameForResults'
var Model = mongoose.model('createdCollectionNameForResults');
Model.find({}).populate('ref_field').exec(function(err, results){
console.log(err, results);
});
I have the following scenario. There is a collection Suppliers and another Invited. Now Invited.supplier = Supplier._id (syntax might be wrong) Invited collection refers to Suppliers in One to Many fashion.
In my html , I have
<template name="mytemplate">
{{#each invited_list}}
{{supplier}}
{{f1}}
{{f2}}
{{/each}}
</template>
I have a helper function
Template.mytemplate.helpers({
invited_list : function(){
return Invited.find({"something"});
}
});
I would like to display {{Suppliers.name}} instead of _id in {{supplier}} in my invited_list . What are my options?
You could create a resolver function such as:
Template.mytemplate.helpers({
invited_list : function(){
return resolveSupplierToNames(Invited.find({"something"}).fetch());
}
});
function resolveSupplierToNames(invitedList) {
for (var i=0; i<invitedList.length; i++) {
invitedList[i].supplier = Suppliers.findOne({_id: invitedList[i].supplier}).name;
}
return invitedList;
}
There are generally two options with mongodb, one is the above (manual). The second is to use DBRefs. However I'm not sure meteor supports DBRefs completely yet. As suggested in the mongodb docs theres nothing wrong with doing it manually.
Update
Meteor has since introduced a transform function, you can do something similar like:
Template.mytemplate.helpers({
invited_list : function(){
return Invited.find({"something"},{transform:function(doc) {
doc.supplier_name = Suppliers.findOne({_id: doc.supplier_id}).name;
return doc;
});
}
});