meteor iterate through array - mongodb

here is my collection
Ques_Coll.insert({question: quest,owner:u_name,comments:[]});
After user enters comment, collection will be updated like this
Ques_Coll.update({_id:this._id},{$push:{comments:{uname:"xxx",cmt_text:"xxx"}}});
Until this working fine
Now, i want to iterate through all the comments and want to display them
how to do it?
this is how i tried and not working
{{#each all_comments.comments}}
<li>{{uname}}</li>
<li>{{cmt_text}}</li>
{{/each}}
this is my template //i think my problem lies in this returning value
all_comments:function()
{
return Ques_Coll.find( {_id:this._id},{fields: {'comments': 1}})
}

Use findOne instead:
Ques_Coll.findOne( {_id:this._id},{fields: {'comments': 1}})
You use find when you're searching for more than one question to match the criteria. But since you're looking for one (the one with the comments), you use findOne instead.

Related

meteor - _id of collection items returning with trailing garbage

I'm returning collection results via a basic find() query and something odd is happening to the {{_id}} I'm receiving. Instead of just the unique id, I'm getting a bunch of trailing garbage that looks like other parts of the document. This is only happening for one collection - the exact same query works perfectly with all my other collections. I'm thinking it may have something to do with how I'm adding collection items, but I'm pretty lost. I can provide more info if needed, but I thought perhaps someone had encountered this before and could advise based on what I've described.
Here's what {{_id}} looks like for documents in the problematic collection:
3D5DWGh9n96BuiC4P""%7B"userId":"hJhLm8iBL9cQDEhzf","limit":10,"skip":0,"props":%7B%7D%7D
Anyone know what's going on here?
NB: Here's extra information I stupidly omitted the first time:
The trailing stuff is not returned when I do I find().fetch(). It's only when I use the easy-search package ( link ) that this happens. Sorry for the lack of clarity earlier.
The helper:
Template.search.helpers({
articlesIndex: () => ArticlesIndex
});
...relevant parts of the template:
{{> EasySearch.Input index=articlesIndex}}
<ul>
{{#EasySearch.Each index=articlesIndex}}
<li>{{title}}</li>
{{/EasySearch.Each}}
</ul>
The hrefs in the search results are where the problematic _ids are.
Actually, it looks like I've figured it out. According to the issues on github, _id is used by the package so I have to refer to __originalId instead. Here's a link in case it helps anyone else: link

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?

Mongo find by regex: return only matching string

My application has the following stack:
Sinatra on Ruby -> MongoMapper -> MongoDB
The application puts several entries in the database. In order to crosslink to other pages, I've added some sort of syntax. e.g.:
Coffee is a black, caffeinated liquid made from beans. {Tea} is made from leaves. Both drinks are sometimes enjoyed with {milk}
In this example {Tea} will link to another DB entry about tea.
I'm trying to query my mongoDB about all 'linked terms'. Usually in ruby I would do something like this: /{([a-zA-Z0-9])+}/ where the () will return a matched string. In mongo however I get the whole record.
How can I get mongo to return me only the matched parts of the record I'm looking for. So for the example above it would return:
["Tea", "milk"]
I'm trying to avoid pulling the entire record into Ruby and processing them there
I don't know if I understand.
db.yourColl.aggregate([
{
$match:{"yourKey":{$regex:'[a-zA-Z0-9]', "$options" : "i"}}
},
{
$group:{
_id:null,
tot:{$push:"$yourKey"}
}
}])
If you don't want to have duplicate in totuse $addToSet
The way I solved this problem is using the string aggregation commands to extract the StartingIndexCP, ending indexCP and substrCP commands to extract the string I wanted. Since you could have multiple of these {} you need to have a projection to identify these CP indices in one shot and have another projection to extract the words you need. Hope this helps.

Mongoid, find object by searching by part of the Id?

I want to be able to search for my objects by searching for the last 4 characters of the id. How can I do that?
Book.where(_id: params[:q])
Where the param would be something like a3f4, and in this case the actual id for the object that I want to be found would be:
bc313c1f5053b66121a8a3f4
Notice the last for characters are what we searched for. How can I search for just "part" of my objects id? instead of having my user search manually by typing in the entire id?
I found in MongoDB's help docs, that I can provide a regex:
db.x.find({someId : {$regex : "123\\[456\\]"}}) // use "\\" to escape
Is there a way for me to search using the regular mongo ruby driver and not using Mongoid?
Usually, in Mongoid you can search with a regexp like you normally would with a string in your call to where() ie:
Book.where(:title => /^Alice/) # returns all books with titles starting with 'Alice'
However this doesn't work in your case, because the _id field is not stored as a string, but as an ObjectID. However, you could add (and index) a field on your models which could provide this functionality for you, which you can populate in an after_create callback.
<shameless_plug>
Alternatively, if you're just looking for a shorter solution to the default Mongoid IDs, I could suggest something like mongoid_token which makes it pretty easy to add shorter tokens/ids to your Mongoid documents.
</shameless_plug>

How to compare 2 mongodb collections?

Im trying to 'compare' all documents between 2 collections, which will return true only and if only all documents inside 2 collections are exactly equal.
I've been searching for the methods on the collection, but couldnt find one that can do this.
I experimented something like these in the mongo shell, but not working as i expected :
db.test1 == db.test2
or
db.test1.to_json() == db.test2.to_json()
Please share your thoughts ! Thank you.
You can try using mongodb eval combined with your custom equals function, something like this.
Your methods don't work because in the first case you are comparing object references, which are not the same. In the second case, there is no guarantee that to_json will generate the same string even for the objects that are the same.
Instead, try something like this:
var compareCollections = function(){
db.test1.find().forEach(function(obj1){
db.test2.find({/*if you know some properties, you can put them here...if don't, leave this empty*/}).forEach(function(obj2){
var equals = function(o1, o2){
// here goes some compare code...modified from the SO link you have in the answer.
};
if(equals(ob1, obj2)){
// Do what you want to do
}
});
});
};
db.eval(compareCollections);
With db.eval you ensure that code will be executed on the database server side, without fetching collections to the client.