I have a user publish and subscribe problem. When I click on a user name, it is supposed to show: [1] user's profile image; and [2] all posts from that user.
However it just shows a loading spinner screen and the below errors. If I try a couple of refresh or re-clicking the name, the page eventually loads with some lag.
I suspect a client race condition but I tried adding a (!this._id) return [ ] or this.ready();, the posts would flash on screen once and not show up thereafter. I cant remove the check as it throws a no check error.
If theres anywhere to simplify showing posts of the user, please kindly advise. Thanks!
error on the browser console:
Exception from Tracker recompute function: meteor.js:930:11
undefined meteor.js:932:11
selected portions of the key error shown on terminal:
> I20170409-11:51:58.787(8)? Exception from sub user id
> BRFKAiwEXKootpbwY Error: Match error: Expected string, got null
> (packages/check/match.js:34:1) I20170409-11:51:58.788(8)? at
> Subscription.<anonymous> (server/server.js:86:2)
> I20170409-11:51:58.788(8)? at Subscription.prepareOptions
> (packages/reywood_publish-composite/packages/reywood_publish-composite.js:440:1)
> I20170409-11:51:58.788(8)? at Subscription._handler
> (packages/reywood_publish-composite/packages/reywood_publish-composite.js:408:1)
> I20170409-11:51:58.788(8)? at packages/check/match.js:107:1
> at Object.exports.Match._failIfArgumentsAreNotAllChecked
> (packages/check/match.js:106:1) I20170409-11:51:58.788(8)? at
> maybeAuditArgumentChecks
> Match failed [400]
The server publish
Meteor.publish('userDetails', function() {
var fields = {
username : 1,
emails : 1,
profile : 1,
md5hash : 1
};
return Meteor.users.find( {}, { fields: fields });
});
Meteor.publishComposite('user', function (_id) {
check(_id, String); // cant remove this check, throws error
//if (!this._id) return this.ready(); or [] doesnt work
return {
find: function() {
return Meteor.users.find({ _id: _id }, {
fields: {
username : 1,
emails : 1,
profile : 1,
md5hash : 1
}
});
},
children: [
{
find: function(user) {
return Posts.find({ userId: user._id });
}
}
]
};
});
Router code
Router.route('/users/:_id', {
name: 'users.show',
onBeforeAction: function () {
if( this.params._id === Meteor.userId() ){
Router.go('profile');
} else {
this.next();
}
}
});
the page js
Template.usersShow.onCreated(function(){
var self = this;
self.autorun(function(){
self.subscribe('user', Router.current().params._id);
});
});
Template.usersShow.helpers({
user: function () {
return Meteor.users.findOne({ _id: Router.current().params._id });
},
posts: function () {
return Posts.find({ userId: Router.current().params._id });
}
});
I read the Pub/Sub section in the official document, but never seen the description about the property _id in the context this.
I think change this._id to _id will work correctly.
Meteor.publishComposite('user', function (_id) {
// Change `this._id` to `_id`
if (!_id) return this.ready(); // or [];
return {
find: function() {
return Meteor.users.find({
_id: _id
}, {
fields: {
username: 1,
emails: 1,
profile: 1,
md5hash: 1
}
});
},
children: [
{
find: function(user) {
return Posts.find({userId: user._id});
}
}
]
};
})
Related
I'm using Azure search on my project, and I want to do an autocomplete text field, it works as expected. here's the code :
const suggestItems = async (req, res) => {
try {
// Reading inputs from HTTP Request
const q = (req.query.q || (req.body && req.body.q));
const top = (req.query.top || (req.body && req.body.top));
const suggester = (req.query.suggester || (req.body && req.body.suggester));
// Let's get the top 5 suggestions for that search term
const suggestions = await client.suggest(q, suggester, { top: parseInt(top) });
//const suggestions = await client.autocomplete(q, suggester, {top: parseInt(top)});
console.log(suggestions.results)
return res.status(status.OK)
.json({ suggestions: suggestions.results})
} catch (error) {
handleError(res, error)
}
}
her's the result :
[
{ text: 'Alpha Aromatics (MA)', document: { id: '4' } },
{ text: 'Alpha Aromatics (USA)', document: { id: '5' } },
{ text: 'Art Land - Winter Palace', document: { id: '6' } },
{ text: 'Alpha Aromatics (USA)', document: { id: '3' } }
]
here's the quesry passed by postman :
{
"q":"ar","top":5,"suggester":"sg"
}
but the problem is , on the result I have just the text and the id of the document , I'm looking for other fields like status for example, how can get that please ?
I am guessing "Status" is one of your index fields, from the question. You need to make sure you mark the fields you need to be returned in the results as retrievable in your index definition. It looks you only have text and id fields as retrievable. For more information: https://learn.microsoft.com/en-us/azure/search/search-what-is-an-index.
Example:
I have Mongoose CastError issue. I made a nodeJs API. At the specific route, it returns data appended with some other data. I saw many fixes available here but my scenario is different.
Here is my model and the problem occurs at fields property.
const deviceSchema = new Schema({
device_id: { type: String, required: true },
user_id: { type: Schema.Types.ObjectId, ref: 'User', require: true },
location_latitude: { type: String, default: '0' },
location_longitude: { type: String, default: '0' },
fields: [{ type: String }],
field_id: { type: Schema.Types.ObjectId, ref: 'Field', required: true },
timestamp: {
type: Date,
default: Date.now,
},
});
and my controller is
exports.getAllDevices = async (req, res) => {
try {
let devices = await Device.find({})
.sort({
timestamp: 'desc',
})
.populate('user_id', ['name']);
// Let us get the last value of each field
for (let i = 0; i < devices.length; i++) {
for (let j = 0; j < devices[i].fields.length; j++) {
if (devices[i].fields[j] !== null && devices[i].fields[j] !== '') {
await influx
.query(
`select last(${devices[i].fields[j]}), ${devices[i].fields[j]} from mqtt_consumer where topic = '${devices[i].device_id}'`
)
.then((results) => {
************** Problem occurs here **************
if (results.length > 0) {
devices[i].fields[j] = {
name: devices[i].fields[j],
last: results[0].last,
};
} else {
devices[i].fields[j] = {
name: devices[i].fields[j],
last: 0,
};
}
************** Problem occurs here **************
});
}
}
}
// Return the results
res.status(200).json({
status: 'Success',
length: devices.length,
data: devices,
});
} catch (err) {
console.log(err);
res.status(500).json({
error: err,
});
}
};
It actually gets data from InfluxDB and appends it to fields property which was fetched from MongoDB as mentioned in my model. But it refused to append and CastError occurs.
After addition, it will look like this
I can't resolve this error after trying so many fixes. I don't know where I'm wrong. Please suggest to me some solution for this.
I can see you are not using devices variable as Mongoose Document. devices is an array of Documents.
I would like to suggest you to use lean() function to convert from Document to plain JavaScript object like
let devices = await Device.find({})
.sort({
timestamp: 'desc',
})
.populate('user_id', ['name'])
.lean();
This is the User schema in mongoose:
var userSchema = new mongoose.Schema({
email: {
type: String,
unique: true,
required: true,
},
name: {
type: String,
required: true,
},
Addtasks: [
{
topic: String,
words: Number,
keywords: String,
website: String,
otherdetails: String,
exampleRadios: String,
deadline: Date,
Date: String,
fileName: String,
Bigpaths: [],
},
],
});
module.exports = mongoose.model('User', userSchema);
I want to use/access the Bigpaths array, which is defined inside the Addtasks array, which is defined in User. Data is already are there in mongoDB, which I have inserted via UI page. I am trying the following code but I am getting this error in console:
data.Addtasks[Object.keys(data.Addtasks).length - 2].Bigpaths.forEach(
(element) => {
// ...
}
)
as
TypeError: Cannot read property 'Bigpaths' of undefined
at \Desktop\grumpytext\routes\index.js:99:71
Code:
const { files } = req;
User.findOne({ email: req.user.email }, function (error, data) {
if (error) {
console.log('Three');
} else if (data) {
if (Object.keys(data.Addtasks).length > 1) {
data.Addtasks[Object.keys(data.Addtasks).length - 2].Bigpaths.forEach(
(element) => {
files.forEach((currentElement) => {
if (element.name == currentElement.filename) {
files.pull(currentElement.filename);
}
});
}
);
}
}
});
How to resolve this error or how to access all the elements of Bigpaths array so that I can iterate it with forEach loop?
I'm not sure here, but I think you need to populate Addtasks prior to manipulating it:
const files = req.files;
User.findOne({email:req.user.email}).populate('Addtasks').exec((error, data) => {
if (error) {
console.log("Three");
}
else
{
if(data)
{
if(Object.keys(data.Addtasks).length > 1)
{
console.log("Addtasks count: " + Object.keys(data.Addtasks).length);
data.Addtasks[Object.keys(data.Addtasks).length - 2].Bigpaths.forEach(element => {
files.forEach(currentElement => {
if(element.name == currentElement.filename)
{
files.pull(currentElement.filename);
}
})
});
}
}
}
});
Please notice the log console.log("Addtasks count: " + Object.keys(data.Addtasks).length); - in case the solution does not work, I advise to add some prints, especially to check if the count of elements is as expected or properties within an object are fine.
I was able to write subscription in meteor and it is working fine. now i need to set state inside the Meteor getMeteorData() method. here is my implemented working method
getMeteorData() {
Meteor.subscribe('Posts', Meteor.userId());
return {
Posts: Posts.find({}, {
sort: {
createdAt: -1
}
}).fetch(),
};
}
also i want it to be something like this. mean i want to set the state inside function. but when i code like below it return exception on the console.
getMeteorData() {
Meteor.subscribe('Posts', Meteor.userId());
let medias = [];
Posts.map(post => {
post.images.map(image => {
medias.push({image: image, post: post})
})
});
this.setState({medias: medias});
return {
Posts: Posts.find({}, {
sort: {
createdAt: -1
}
}).fetch(),
};
}
below is the snap of error error snap
I am trying to update firstName field created in user.profile using onCreateUser:
Accounts.onCreateUser(function(options, user) {
user.profile = options.profile || {};
user.profile.firstName = options.firstName;
return user;
});
Also I use allow:
Meteor.users.allow({
update: function(userId, doc, fields, modifier) {
if (fields === "profile.firstName") {
return true;
}
}
});
When I use:
Meteor.users.update({
_id: Meteor.userId()
}, {
$set: {
profile: "George"
}
});
It works but it is not what I need.
What I need is to update firstName:
Meteor.users.update({
_id: Meteor.userId()
}, {
$set: {
profile.firstName: "George"
}
});
But I get this error:
SyntaxError: missing : after property id
What am I missing?
If you are using the dot notation you need to enclose the whole dotted field name in quotes.
In your case:
Meteor.users.update({
_id: Meteor.userId()
}, {
$set: {
"profile.firstName": "George"
}
});
Read more about updating an embedded field.