meteor update method not working - meteor

this is my colletion:
{
"_id" : "Kan6btPXwNiF84j8e",
"title" : "Chapter Title 1",
"businessId" : "qmWJ3HtZrpka8dpbM",
"createdBy" : "GfdPfoPTiSwLv8TBR",
"sections" : [
{
"id" : "T5KAfTcCb7pCudT3a",
"type" : "TEXT",
"data" : {
"text" : "<h1>2</h1><h1>asd</h1>"
},
"createdAt" : ISODate("2016-12-03T10:35:59.023Z"),
"updatedAt" : ISODate("2016-12-03T10:35:59.023Z")
}
],
"createdAt" : ISODate("2016-12-02T12:15:16.577Z"),
"updatedAt" : ISODate("2016-12-03T12:54:50.591Z")
}
this is the meteor method I am calling from client side
deleteSection: function (section_id, chapter_id) {
chaptersCollection.update(
{$and: [{_id: chapter_id}, {'sections.id': section_id}]},
{$pull: {'sections': {'id': section_id}}},
function (err, numAffected) {
if (err) {
console.log(err);
return err;
}else{
console.log(numAffected);
}
});
return 'Section Successfully Deleted';
}
in callback function of meteor method, it returns 1 as affected rows. But on server document is not updating.
Any suggestion where am I wrong?

Do you really need $and?
deleteSection: function (section_id, chapter_id) {
chaptersCollection.update(
{_id: chapter_id, 'sections.id': section_id},
{$pull: {'sections': {'id': section_id}}},
function (err) {
if (err) {
console.log(err);
return err;
}else{
console.log('success');
return 'success';
}
});
}

I had a similar issue when I tried to use pull in a project. So instead of using $pull, I handled the array outside of the database and then set the array as the one I handled outside. So maybe you can try something like that as an alternative way
deleteSection: function (section_id, chapter_id){
const oldArray = chaptersCollection.findOne(chapter_id).sections;
const newArray = oldArray.filter(function(section) {
return section.id !== section_id
});
chaptersCollection.update({_id: chapter_id},
{$set: {sections: newArray}},
function (err, numAffected) {
if (err) {
console.log(err);
return err;
}else{
console.log(numAffected);
}
});
return 'Section Successfully Deleted';
}

Related

Using Vue, but I can't query information from Firebase to display values in a chart/graph (google charts or GChart). "Error: Table has no columns."

This code is inside a .vue file. Receiving the "Error: Table has no columns." Inside the methods function, it won't receive the values from firebase to display a chart/graph to web app. What am I doing incorrectly? I think the values am I trying to receive inside "chartData:[ ]" or "mounted()" is incorrect and may be causing the issue. Any help is much appreciated.
export default {
name: "App",
components: {
GChart
},
methods: {
getHumidity(){
get(
query(ref(db, auth.currentUser.uid + "/Environment/humidity"),
orderByChild("humidity")
)
).then((snapshot) => {
if (snapshot.exists()) {
console.log(snapshot.val());
for (const item in snapshot.val()) {
this.pgoods.push({
humidity: snapshot.val()[item].humidity,
expir: snapshot.val()[item].humidity,
});
}
} else {
this.pgoods = [];
}
return float(snapshot.val());
});
}
getPressure(){
get(
query(ref(db, auth.currentUser.uid + "/Environment/pressure"),
orderByChild("pressure")
)
).then((snapshot) => {
if (snapshot.exists()) {
console.log(snapshot.val());
for (const item in snapshot.val()) {
this.pgoods.push({
pressure: snapshot.val()[item].pressure,
expir: snapshot.val()[item].pressure,
});
}
} else {
this.pgoods = [];
}
return float(snapshot.val());
});
}
getTime(){
get(
query(ref(db, auth.currentUser.uid + "/Environment/time"),
orderByChild("time")
)
).then((snapshot) => {
if (snapshot.exists()) {
console.log(snapshot.val());
for (const item in snapshot.val()) {
this.pgoods.push({
time: snapshot.val()[item].time,
expir: snapshot.val()[item].time,
});
}
} else {
this.pgoods = [];
}
return float(snapshot.val());
});
},
},
data(){
return{
chartData: [
["Time", "Pressure", "Humidity"],
[this.getTime(), this.getPressure(), this.getHumidity()],
[this.getTime(), this.getPressure(), this.getHumidity()],
],
},
mounted(){
this.getTemperature();
this.getHumidity();
},
}

How do I access data in GraphQL if not by the id?

I'm using GraphQL with Meteor and Pup v2, and I have a problem accessing the users data via a special ID provided to every user on signup, this ID will be used in a link (mysite.com/user/specialId) so other users can view the searched users account. Problem is, I can't get the data with the special ID, I can't get any data back if I don't pass in the users _id provided by MongoDB. Below I have a bunch of the code used:
Attempt 1
I tried to use a custom on-the-go way just to be able to at least access the data to see if it works (and then implement it correctly later)
const GET_USER_DETAILS = gql`
query user($userId: String) {
user(userId: $userId) {
userId
username
_id
}
}
`;
Here I export so I can get the data:
export default compose(
graphql(GET_USER_DETAILS, {
options: ({ match }) => ({
fetchPolicy: 'no-cache',
variables: {
// existing specialId for testing purposes, to be replaced with match.params.userId
userId: "J4xZzvvhBDSEufnBn",
},
}),
}),
)(PublicProfileView);
This returns a 400 error Network error: Response not successful: Received status code 400 error and after multiple attempts, I could not fix it, so I tried a different approach...
Attempt 2
I tried to go deep into the files and change the GraphQL. Created a new query:
query userById($userId: String) {
userById(userId: $userId) {
...UserAttributes
}
}
(Mentioned fragment)
fragment UserAttributes on User {
_id
name {
...
}
username
emailAddress
oAuthProvider
roles {
...
}
settings {
...
}
userId
}
Tried to add new item in API:
type Query {
...
userById(userId: String): User
...
}
Resolver:
resolvers: {
Query: {
...
userById: (parent, args) => {
// Assuming args equals an object like { _id: '123' };
return UserQueries.userById(args);
},
},
},
query.js, attempt 1:
userById: (parent) => queryUsers.find({ userId: parent.userId }, { sort: { createdAt: 1 } }).fetch()
Attempt 2:
userById: (parent, args, context) => {
return queryUsers({
userId: parent.userId,
});
},
And finally
Attempt 3
I tried to modify the get query
const getQueryModified = (options) => {
// console.log(options.userId)
try {
return options.userId
? { 'userId': options.userId }
: { userId: options.userId };
} catch (exception) {
throw new Error(`[queryUsers.getQuery] ${exception.message}`);
}
};
Here is the original query I tried to modify:
const getQuery = (options) => {
try {
return options.search
? {
_id: { $ne: options.currentUser._id },
$or: [
{ 'profile.name.first': options.search },
{ 'profile.name.last': options.search },
{ 'emails.address': options.search },
// { 'userId': options.search },
{ 'services.facebook.first_name': options.search },
{ 'services.facebook.last_name': options.search },
{ 'services.facebook.email': options.search },
],
}
: { _id: options.currentUser._id };
} catch (exception) {
throw new Error(`[queryUsers.getQuery] ${exception.message}`);
}
};
Unfortunately this was also unsuccessful, the best I get from these when executing the below query is null...
userById(userId: "J4xZzvvhBDSEufnBn"){
username
}
All I want is to get the user data from their userId and not their _id, but I can't seem to figure out how to do it

Meteor Tracker autorun fires 2 times

This Meteor client code tries to make the Tracker.autorun to run once but as it appears to be that it has to run twice, once for setting and once for reactiveness.
Which is fine but it is firing 3 times. Once for setting and 2 for reacting even though the server only updated the user.profile.abc once.
To test it, I run this code in the mongodb console and the the iamge attached is what I got which confirms it fires twice.
How can I get it to run only once for responding to the changes in the users collection? Thanks
db.users.update({_id: Meteor.userId()},{$set: {'profile.ABC': ['a','b']}}).pretty()
//client
Meteor.call('cleanABC', (err) => {
if (!err) {
ABCListener();
}
});
ABCListener: () => {
Tracker.autorun(() => {
if (Meteor.userId()) {
console.log('auto run invoked');
if (Meteor.user().profile.ABC) {
const myArray = Meteor.user().profile.ABC;
//myFunction(myArray);
console.log('condition true');
} else {
console.log('condition false');
}
}
});
}
//server
'cleanABC': function() {
return Meteor.users.update({
_id: Meteor.userId()
}, {
$unset: {
'profile.ABC': ''
}
});
}
//and some where else in the code
Meteor.users.update({
_id: userId
}, {
$set: {
'profile.ABC': myArray
}
}, (err) => {
if (!err) {
console.log('just sent the array');
}
});
I think the problem is that you are just calling Tracker.autorun everytime you call the method.
I think if you change your client code to:
//client
ABCListener: () => {
Tracker.autorun(() => {
if (Meteor.userId()) {
console.log('auto run invoked');
if (Meteor.user().profile.ABC) {
const myArray = Meteor.user().profile.ABC;
//myFunction(myArray);
console.log('condition true');
} else {
console.log('condition false');
}
}
});
}
Meteor.call('cleanABC');
it should work.

How to use Promise in angular2 with firebase to transform login to service

I'm learning how to code. I'm struggling with promise, and how to use them.
I want to accomplish login using Facebook with Firebase.
The code works perfectly when I don't use this as service
authWithFacebook(){
this.usersRef.authWithOAuthPopup("facebook", (error) => {
if (error) {
console.log(error);
}else if (this.isLoggedIn && this.newUser) {
this.usersRef.child(this.authData.uid).set({
NomComplet: this.authData.facebook.displayName,
ProfileCached: this.authData.facebook.cachedUserProfile,
Nom : this.authData.facebook.cachedUserProfile.last_name,
Prenom : this.authData.facebook.cachedUserProfile.first_name,
ProfileImg: this.authData.facebook.profileImageURL,
Agemoyen : this.authData.facebook.cachedUserProfile.age_range,
Localite : this.authData.facebook.cachedUserProfile.locale,
});
}
});
console.log("je suis connecté" + " " + this.authData.facebook.displayName )
}
I attemped to transform my code into a service, which can be used in the entire app. But it doesn't work:
authWithOAuth(){
return new Promise(function(resolve, reject){
this.usersRef.authWithOAuthPopup("facebook", (error) => {
if (error) {
console.log(error);
reject(error);
}else {
resolve();
}
})
})
}
Can anyone can help me with this or tell me which doc to read to fully understand this?
You need to refactor your code like this:
authWithFacebook(){
this.authService.authWithOAuth().then(
() => {
this.usersRef.child(this.authData.uid).set({
NomComplet: this.authData.facebook.displayName,
ProfileCached: this.authData.facebook.cachedUserProfile,
Nom : this.authData.facebook.cachedUserProfile.last_name,
Prenom : this.authData.facebook.cachedUserProfile.first_name,
ProfileImg: this.authData.facebook.profileImageURL,
Agemoyen : this.authData.facebook.cachedUserProfile.age_range,
Localite : this.authData.facebook.cachedUserProfile.locale,
});
},
(err) => {
console.log(error);
}
);
}
to use the then method of promises.

Reactive Data Source in METEOR#1.3-modules-beta.6 and React

I am building a Chat app in Meteor 1.3, ES6 and React.
I have 3 collections:
1. People: Who has an array of conversations that the person are involved.
2. Conversations: That also have the people that are involved.
3. Messages: That has a conversation_id field to relate to second collection.
So I am using reywood:publish-composite package, to manage the reactive joins:
=> Get Conversations for this People (user)
=> Get the Messages of all the Conversations of this user
=> Filter messages according to the conversation selected (a react state)
I am also using the package React-Komposer from Kadira.
This is my code:
// publications.js
Meteor.publishComposite('compositeChat', function (people_id) {
return {
find() {
return Collections.People.find({_id: people_id});
},
children: [
{
find(people) {
return Collections.Conversations.find(
{_id: {$in: people.conversations }},
{sort: {'lastMessage.date': -1}}
);
}
},
{
find(people) {
return Collections.Messages.find(
{conversation_id: {$in: people.conversations }},
{sort: {date: 1}}
);
}
},
{
find(people) {
return Collections.People.find(
{_id: {$in: people.contacts }}
);
}
}
]
};
});
// AppContainer.js
import {composeAll, composeWithTracker} from 'react-komposer';
import AppWrapper from '../AppWrapper.jsx';
import * as Collections from '../../../../lib/collections/collections.js';
function composeChat(props, onData) {
let user;
if (!Meteor.userId()) {
user = 'qXSWv64qKaEPAu5yp';
} else {
user = Meteor.userId();
//console.log('Meteor.userId()', Meteor.userId());
}
const
chatSub = Meteor.subscribe('compositeChat', user);
if (chatSub.ready()) {
const chatData = {
chatLoading:
!chatSub.ready(),
myUserData:
Collections.People.findOne({_id: user}),
myContacts:
Collections.People.find(
{_id: { $ne: user}}, { sort: { name: 1 } }
).fetch(),
myConversations:
Collections.Conversations.find(
{}, { sort: { date: -1 } }
).fetch(),
noConversationContacts:
(function () {
return myFunctions.chat.noConversationContacts(
Collections.People.find(
{_id: { $ne: user}}
).fetch(),
Collections.Conversations.find().fetch()
);
}()),
myMessages:
Collections.Messages.find(
{}, {sort: {'lastMessage.date': -1}}
).fetch(),
myOtherPeople:
(function () {
return myFunctions.chat.getTheOtherPeople(
Collections.Conversations.find().fetch(),
user
);
}()),
unreaded:
(function () {
return myFunctions.chat.countUnreadedMessages(
user,
Collections.Conversations.find().fetch(),
Collections.Messages.find().fetch()
);
}())
};
console.log('chatData', chatData);
onData(null, {chatData});
}
}
export default composeWithTracker(composeChat)(AppWrapper);
The problem is: When new message is added, I am not getting the update in the UI, but the data is there (in Mongo), so if I refresh the page, I get the new messages...
In my previous version of the app (Meteor 1.2) this reactive joins worked perfectly.
What could be wrong?
Does publish-composite package not work with Meteor 1.3?
Does publish-composite can't be used with React-Komposer?
Do I have to mix them in other way?
Is there another option (with or without this packages) to manage reactive joins in Meteor 1.3?
Thanks

Resources