I have the collection "menu" with structure:
{
"_id" : "vJQr7EuieDHMuX2nx" "section" : "vine" "price" : "200" "category" : "bar"
"_id" : "vJQr7EuieDHMuX4rf" "section" : "beer" "price" : "200" "category" : "kitchen"
"_id" : "vJQr7EuieDHMuX5tg" "section" : "milk" "price" : "200" "category" : "kbar"
"_id" : "vJQr7EuieDHMuX4sc" "section" : "beer" "price" : "200" "category" : "kitchen"
"_id" : "vJQr7EuieDHMuX2xs" "section" : "vine" "price" : "200" "category" : "bar"
}
I want to show the user only "section" without repeating
For this I used
Menu.aggregate([{$group:{_id:"$section"}}])
but it's not working
How can I do this? May be to use a different method?
Server side:
Meteor.methods({
'getSections': function () {
var pipeline = [{$group:{_id:"$section"}}];
var result = Menu.aggregate(pipeline);
var sections = [];
for (i = 0; i < result.length; i++) {
sections.push(result[i]._id);
};
console.log(sections);
return sections;
}
});
result in the server: [ 'vine', 'beer', 'milk' ]
Client side:
Template.MobBarMenu.helpers({
'list': function(){
this.render('MobBarMenu', {});
},
'listSections': function () {
Meteor.call('getSections', function (err, data) {
console.log(data);
// return data;
});
}
});
template name="MobBarMenu"
{{#each listSections}}
{{this}}
{{/each}}
template
I don't know where to find the solution
You probably want an advanced publication. On your template code, add a named collection (only on client). Then you can create a helper to get the data and subscribe to the publication.
const Sections = new Mongo.Collection('sections');
Template.Menu.onCreated(function () {
this.subscribe('sections')
})
Template.Menu.helpers({
sections() {
return Sections.find();
}
});
Then, create a publication that writes to this.
Meteor.publish('sections', function () {
const handle = Menu.find({}, {
fields: {
_id: 0
section: 1
}
}).observe({
added: doc => this.added('sections', doc.section, doc),
changed: doc => this.changed('sections', doc.section, doc),
removed: doc => this.removed('sections', doc.section, doc)
});
this.ready();
this.onStop(() => handle.stop())
})
Meteor uses MiniMongo - it's own wrapper of nodejs MongoDB driver.
And by default collecions has no method aggregate. You can find it in a few packages, like monbro:mongodb-mapreduce-aggregation.
Or (which better imo) you can get access to raw collection with native to Meteor rawCollection method:
Menu.rawCollection().aggregate(pipeline, function(err, res) {
//do stuff here
})
Related
I have a problem with GiftedChat, the messages appear completely disorganized in the app and even looking for messages directly from the firebase (where it is correct), the app does not get a logical order. When sending is organized, however the problem is when you load the messages. I'm completely lost
loadMessages = async () => {
const { user } = this.props;
const matchId = this.props.navigation.getParam('matchId');
const data = (await firebase.database().ref(`matchs/${matchId}/messages`).limitToLast(300).once('value')).val();
let messages = [];
if(data){
Object.keys(data)
.forEach(messageId => {
let message = data[messageId];
if(_.get(message, 'user._id') !== user.uid) _.push(message);
messages.push(message);
});
}
this.setState(() => ({
messages,
}));
}
My JSON:
{
"-LkAMYoS3fySk46Pbpan" : {
"_id" : "f5ba3d9a-c346-4f79-b371-c5d54798567e",
"createdAt" : 1563558815857,
"text" : "First message",
"user" : {
"_id" : "BVY4MDwSaaSDI2bAGjwkZlYktsK2",
"avatar" : "https://firebasestorage.googleapis.com/v0/b/wefound-760f2.appspot.com/o/users%2FBVY4MDwSaaSDI2bAGjwkZlYktsK2%2Fphotos%2Fk1xuqv26wdrjxoxmp8m.jpg?alt=media&token=7c16a0e4-2cb8-45a5-83a4-635d49c71180",
"name" : "Rafael"
}
},
"-LkAMZiITDxHE1WfCBGC" : {
"_id" : "c2755b48-136d-4a68-b283-377ebac7df8e",
"createdAt" : 1563558819564,
"text" : "Second message",
"user" : {
"_id" : "BVY4MDwSaaSDI2bAGjwkZlYktsK2",
"avatar" : "https://firebasestorage.googleapis.com/v0/b/wefound-760f2.appspot.com/o/users%2FBVY4MDwSaaSDI2bAGjwkZlYktsK2%2Fphotos%2Fk1xuqv26wdrjxoxmp8m.jpg?alt=media&token=7c16a0e4-2cb8-45a5-83a4-635d49c71180",
"name" : "Rafael"
}
},
"-LkAM_l4o_w_QeCsYRc8" : {
"_id" : "65772152-afd9-4353-b752-ac65978a536d",
"createdAt" : 1563558823838,
"text" : "Third message",
"user" : {
"_id" : "BVY4MDwSaaSDI2bAGjwkZlYktsK2",
"avatar" : "https://firebasestorage.googleapis.com/v0/b/wefound-760f2.appspot.com/o/users%2FBVY4MDwSaaSDI2bAGjwkZlYktsK2%2Fphotos%2Fk1xuqv26wdrjxoxmp8m.jpg?alt=media&token=7c16a0e4-2cb8-45a5-83a4-635d49c71180",
"name" : "Rafael"
}
},
"-LkAMcSSTOP7L1CwyiU4" : {
"_id" : "e69f3a72-0f4e-4c06-a763-518ef1984aa0",
"createdAt" : 1563558834859,
"text" : "Fourth message",
"user" : {
"_id" : "BVY4MDwSaaSDI2bAGjwkZlYktsK2",
"avatar" : "https://firebasestorage.googleapis.com/v0/b/wefound-760f2.appspot.com/o/users%2FBVY4MDwSaaSDI2bAGjwkZlYktsK2%2Fphotos%2Fk1xuqv26wdrjxoxmp8m.jpg?alt=media&token=7c16a0e4-2cb8-45a5-83a4-635d49c71180",
"name" : "Rafael"
}
},
"-LkAMduvBrEnUG6POGKt" : {
"_id" : "897b2042-25dc-46ec-a5f3-5bdc1fc355dd",
"createdAt" : 1563558840853,
"text" : "Fifth message",
"user" : {
"_id" : "BVY4MDwSaaSDI2bAGjwkZlYktsK2",
"avatar" : "https://firebasestorage.googleapis.com/v0/b/wefound-760f2.appspot.com/o/users%2FBVY4MDwSaaSDI2bAGjwkZlYktsK2%2Fphotos%2Fk1xuqv26wdrjxoxmp8m.jpg?alt=media&token=7c16a0e4-2cb8-45a5-83a4-635d49c71180",
"name" : "Rafael"
}
}
}
I gave console.tron.log () in the messages and they appear disorganized exactly the same is in the app, the problem is in the component?
1 - refers to the function that loads the messages.
2 - JSON file
There are two steps to ordering the data:
Telling the Firebase Database server to return the child nodes in the correct order.
Maintaining that order in your client-side code.
As far as I can tell your code does neither of these, which means the nodes end up in whatever order your client uses for JSON properties (which are by definition unordered).
Let's first see how to retrieve the data in the correct order from Firebase:
const snapshot = (await firebase.database().ref(`matchs/${matchId}/messages`).orderByChild('createdAt').limitToLast(300).once('value'));
The above orders all child nodes by the value of their createdAt property, then returns the last 300 in order to the client.
You'll note that I don't call val() here yet. The reason for that is that snapshot.val() returns a JSON object, and properties in a JSON object have no defined order. So if you call .val() too early, you lose the ordering information that the server returned.
Next up is processing them in the client-side code to not lose that order, which depends on using DataSnapshot.forEach():
data.forEach((message) => {
messages.push(message.val());
})
Finally, I am able to solve this problem by sorting the JSON which is coming to from the server based on the date and time(CreatedAT).
If the JSON data stored in a variable called discussion then your code should be
discussion.sort(function compare(a, b) {
var dateA = new Date(a.createdAt);
var dateB = new Date(b.createdAt);
return dateB - dateA;
});
In your case, data or messages is the one which holds the JSON. Add this code once you get the code in JSON format.
Thank you.
I am using mongodb with nodejs to find data in embedded document. strange fact is query works in database but not in actual nodejs code.
here is my data object:
{
"_id" : ObjectId("5c65866488a1c53464e46dc7"),
"cat_lang" : [
{
"_id" : ObjectId("5c65866488a1c53464e46dc8"),
"en" : "temp",
"it" : "temp"
}
],
"providers" : [
{
"_id" : ObjectId("5c65866488a1c53464e46dc9"),
"provider_name" : "temp0",
"url" : "http://uber.com",
},
{
"_id" : ObjectId("5c65866488a1c53464e46dca"),
"provider_name" : "temp1",
"url" : "http://uber2.com",
}
]}
I have tried these queries in the mongodb shell works perfectly fine.
db.sideservices.findOne({"_id" : ObjectId("5c65866488a1c53464e46dc7")},{providers: {$elemMatch: {"_id" : ObjectId("5c65866488a1c53464e46dca")}}})
AND
db.sideservices.find({"providers._id":ObjectId("5c65866488a1c53464e46dca")},{'providers.$':1})
But when using the same functions in nodejs, it returns the whole object instead document with the given id.
this.db.collection('sideservices').find({'providers':{'$elemMatch':{'_id':ObjectId('5c65866488a1c53464e46dca')}}}).toArray((err,res) => {...})
You can do this way
this.collection("sideservices").find({
"providers": { "$elemMatch": { "_id": ObjectId("5c65866488a1c53464e46dca") } }
})
.project({
"providers": { "$elemMatch": { "_id": ObjectId("5c65866488a1c53464e46dca") } }
})
.toArray((err,res) => {...})
I was just wondering if someone could help me with an issue I'm having in my Ionic app.
I'm having trouble getting my head around nested firebase queries and being able to update the ionic view asynchronously. I'm not using angularfire or anything like that.
My database structure is the following...
"posts" : {
"-KguJ95gTreWH5AT5lQ1" : {
"category" : "Example",
"description" : "This is a test description!!!",
"userID" : "SeMpRKxczcSCFpnkVDTU2pxCDV12"
},
"-Kh--WhNsWAXqs1jLfXu" : {
"category" : "Example 2",
"description" : "Test description .....",
"userID" : "SeMpRKxczcSCFpnkVDTU2pxCDV12"
}
},
"user-posts" : {
"SeMpRKxczcSCFpnkVDTU2pxCDV12" : { // User ID
"-KguJ95gTreWH5AT5lQ1" : { // Post
"category" : "Example",
"description" : "This is a test description!!!",
"userID" : "SeMpRKxczcSCFpnkVDTU2pxCDV12"
},
"-Kh--WhNsWAXqs1jLfXu" : { // Post
"category" : "Example 2",
"description" : "Test description .....",
"userID" : "SeMpRKxczcSCFpnkVDTU2pxCDV12"
}
}
}
And my call to the database is the following...
const posts: Post[] = [];
this.database.ref('posts').orderByChild('category').equalTo(this.category.name).once('value')
.then(
(posts) => {
//console.log(posts.val());
posts.forEach(function(childPost) {
var post = childPost.val();
var user = {};
firebase.database().ref('users/'+post.userID).on('value', function(snapshot){
user = snapshot.val();
// console.log(user);
});
var newPost = new Post(childPost.key, post.category, post.description, user );
//console.log(JSON.stringify(newPost));
posts.push(newPost);
});
}
).catch(
(err) => {
console.log(err);
}
);
The problem I'm having is that my view is rendered before the data from the second query is resolved. I have to leave the view and re-enter for the change detection to update my view.
I've read about things such as nested observables etc, but that just seems like overkill for what I'm trying to do ( Or I may be wrong ). Any help would be appreciated?
I have a collection which represents the uploaded files for the user with a structure like so:
{
_id : SKHdspjhs92346
files : [ { file_name : "1.txt" , file_path : "/home/test1"/} , { file_name : "2.txt" , file_path : "/home/test2"/} ]
}
I want to subscribe to this collection array changings.
So when client uploads a file im doing a push :
AttachmentsList.update({_id : id},
{ $push: { files : {file_name : fileName, file_path: filePath}}});
And a pull when deleted:
AttachmentsList.update( {"_id": id }, {"$pull": { "files" : {file_name : fileName,file_path: filePath} } } );
I want the elements dinamically change in template. Is it possible to do so? Currently i have this publisher
Meteor.publish("attachments_list_limited", function (count,id) {
var test = AttachmentsList.find({_id : id}, { "files.$": 1 },{limit: count}, {sort: {"files.file_name": -1}});
console.log("changed, gout elements: " + test.count());
return test;
});
But it doesnt work reactively like that.
You could have a look at https://github.com/peerlibrary/meteor-reactive-publish to try to make your publish reactive to the user structure's updates through #autorun.
I have issue regarding publishing collection.
I have model of each document in collection.
{
"_id" : "8SwmMoMHTREDNDQTN",
"persons" : [
{
"userId" : "29pr753gmyDxQZzo6",
"lastReadTime":""
},
{
"userId" : "gWKbYKiQsFzdCTwkz",
"lastReadTime":""
}
]
}
Now i want to publish document which persons.userId have current user id
Here is my publish code
Meteor.publish("chatRooms", function(){
return userData.find({persons:{$elemMatch:{userId:this.userId}}});
});
But is it is nothing
i had also try below code
Meteor.publish("chatRooms", function(){
return userData.find({"persons.userId":this.userId});
});
But also getting result data 0
How can i publish this way?