Sorting algorithm is activated only after refresh - mongodb

My code sorts the my collection, but If I make an admin to change someones rank, the change only gets activated after a refresh. Am very confused as to why, and how to fix this, any help would be awesome!
Meteor.publish("sortingAlgo", function(){
return og.find({},{ sort: {rank: 1,scores: 1}});
});

Make sure you're also sorting on the client after you subscribe. In publications, sort is mostly useful when used in conjunction with limit.

You publication code is right.
You need to sort the value on client side as well. Because whenever you add a new doc its update the publication. But on the client side your value is append in you mini mongo.To fix this you need to sort the data on client side before using this.
//Subscribe your publication.
Template.name.helpers({
'data: function() {
return og.find({},{ sort: {rank: 1,scores: 1}});
}
})

Related

Mongodb Stitch realtime watch

What I intend to achieve is some sort of "live query" functionality.
So far I've tried using the "watch" method. According to the documentation:
You can open a stream of changes that match a filter by calling
collection.watch(delegate:) with a $match expression as the argument.
Whenever the watched collection changes and the ChangeEvent matches
the provided $match expression, the stream’s event handler fires with
the ChangeEvent object as its only argument
Passing the doc ids as an array works perfectly, but passing a query doesn't work:
this.stitch.db.collection<Queue>('queues')
.watch({
hospitalId: this.activehospitalid
}));
I've also tried this:
this.stitch.db.collection<Queue>('queues')
.watch({
$match: {
hospitalId: this.activehospitalid
}
},
));
Which throws an error on the console "StitchServiceError: mongodb watch: filter is invalid (unknown top level operator: $match)". The intention is watch all documents where the field "hospitalId" matches the provided value, or to effectively pass a query filter to the watch() method.
After a long search I found that it's possible to filter, but the query needs to be formatted differently
this.stitch.db.collection<Queue>('queues')
.watch({
$or: [
{
"fullDocument.hospitalId": this.activehospitalid
}
]
},
));
For anyone else who might need this, please note the important fullDocument part of the query. I havent found much documentation relating to this, but I hope it helps

Prevent rounding errors when using $inc in mongodb on US currency?

I am calling update from node to add money to a user's account. Starting from 0, these two sequential updates:
83.94 and then 546.13 result in 630.0699999999999.
This is the same result as if you do this in JS
83.94+566.13
This is the mongo call:
xxx.update({_id: xId},
{
$inc: {money: dollars}
});
Is there any way to prevent this and get reasonable behavior? (besides converting to pennies instead of dollars).
Do I really have to "round to 2" every time I read this field?
Thanks #ryan. Just what I needed.
https://docs.mongodb.com/manual/tutorial/model-monetary-data/
https://docs.mongodb.com/manual/core/shell-types/#shell-type-decimal

How do I return a value from a specific field in a different collection in Meteor?

I've bought the Discover Meteor book and gone through the tutorial. I am still unsure of a few sections and have run into a problem which I can't get working.
I have two collections.
Computers = new Mongo.Collection('computers');
Apps = new Mongo.Collection("apps");
On the server I am publishing:
Meteor.publish('computers', function() {
return Computers.find();
});
Meteor.publish('apps', function() {
return Apps.find();
});
On the client subscribing using Iron Router:
Router.configure({
waitOn: function() {
return [Meteor.subscribe('computers'),
Meteor.subscribe('apps'),
Meteor.subscribe('users')];
}
});
In one collection I have referenced a document with the id of another document in another collection.
Computers.insert({
_id: sd9f9sdf699,
name: 'Mac1'
});
Apps.insert({
_id: ewf4y34349f,
name: 'App One',
version: '1.0',
computerId: sd9f9sdf699
});
I am then using an {{#each}} block to iterate through the documents in the apps collection
{{#each apps}}
{{> appItem}}
{{/each}
<template name="appItem">
<tr>
<td><input type="checkbox" name="checked" class="ui checkbox"></td>
<td>{{name}}</td>
<td>{{version}}</td>
<td>{{computerName}}</td>
</tr>
</template>
and when I get to the computerId field, I would like to match the document in the computers collection and then return the name of the computer instead of the id.
Here is my app_item.js code:
Template.appItem.helpers({
computerName: function() {
var id = this.computerId;
var compName = Computers.find({_id: id}, {fields: {name: 1} }).fetch();
return compName;
}
});
I am obviously missing something here but I can't seem to wrap my head around what it is.
If possible I would please prefer an answer that would teach me what I am doing wrong instead of a copy & paste solution on how to fix it. I seem to have a problem understanding this and would appreciate any advice what programming theory I should be reviewing.
Thanks for reading!
Piotr
Your helper code should use findOne() instead of find() function. find() returns coursor that has function fetch() which returns array. findOne() returns one document.
Template.appItem.helpers({
computerName: function() {
var comp = Computers.findOne(this.computerId, {fields: {name: 1} });
return comp.name;
}
});
This is one way how to handle joins in Meteor. I've found better way: http://meteor.hromnik.com/blog/joins-in-meteorjs-and-mongodb
One thing you could consider is changing your datamodel to more of a mongo style document structure where you are storing the computerid + computername both on in the apps collection. This prevents extra queries and the only downside is you need to update 2 fields instead of 1 when youre changing the computer values in a specific app document.
You can then simply display the computername with {{computerName}} without the need for a helper.
You could also store each app-computer relation in an array in the computer collection so you can easily request all installed apps on a certain computer without the need to run extra queries for each and every app. But this is not really needed in this case since both collection contain so few fields and you could just get all apps with a simple mongo query as well. Another usefull field (just a guess) could be something like installedAppsAmount in the computer document so you can list the amount of apps on each coputer without extra queries.
All of this is based on assumptions tho and really depends on your usecase.
Hope this is usefull for you.
Im not really sure why your example is not working tho based on this info: is this.computerId correct in your helper and what is compname returning if you display it in your console?

Meteor - Cannot Access All Read Operations

I'm new to Meteor. I've been stuck on this problem for a while. I can successfully adds items to a collection and look at them fully in the console. However, I cannot access all of the read operations in my .js file.
That is, I can use .find() and .findOne() with empty parameters. But when I try to add .sort or an argument I get an error telling me the object is undefined.
Autopublish is turned on, so I'm not sure what the problem is. These calls are being made directly in the client.
This returns something--
Template.showcards.events({
"click .play-card": function () {
alert(Rounds.find());
}
})
And this returns nothing--
Template.showcards.events({
"click .play-card": function () {
alert(Rounds.find().sort({player1: -1}));
}
})
Sorry for the newbie question. Thanks in advance.
Meteor's collection API works a bit differently from the mongo shell's API, which is understandably confusing for new users. You'll need to do this:
Template.showcards.events({
'click .play-card': function() {
var sortedCards = Rounds.find({}, {sort: {player1: -1}}).fetch();
console.log(sortedCards);
}
});
See this for more details. Also note that logging a cursor (the result of a find) probably isn't what you want. If you want to see the contents of the documents, you need to fetch them.
Rounds.find().sort({player1: -1}) returns a cursor, so you will want to do this:
Rounds.find().sort({player1: -1}).fetch();
Note that this returns an Array of document objects. So you would do something more like this:
docs = Rounds.find().sort({player1: -1}).fetch();
alert(docs[0]);

Using Sails.js is it possible to sort with waterline by true/false?

I'm using Sails.js and thus, Waterline and I'm wondering if the following is possible?
teamFind: function(req,res,next){
User.find().skip(req.param('listPage')).limit(26).sort('school').sort('officialUser').exec(function(err,users){
res.view({
teams:users,
nextPage: parseInt(req.param('listPage'),10)+26
});
});
},
What I'm wanting to do is return the users sorted by school and then move the "Official Users" to the top of that list. Currently this just returns everything in alphabetic order. Is the issue that 'officialUser' is a boolean?
Solved! The main issue was that I had objects I wanted to sort in the wrong order. Also, I needed to add 'desc' to the 'officialUser' sort.