Jaybruh
Jaybruh

Reputation: 343

How to find and return a specific field from a Mongo collection?

Although I think it is a general question, I could not find a solution that matches my needs.

I have 2 Mongo collections. The 'users' collection and the second one 'dbInfos'.

Now, I have a template called 'Infos' and want the already existing fields in the Mongo collections to be presented to the user in input fields in case there is data in the collection. When no data is provided in the database yet, it should be empty.

So here is my code, which works fine until I want to capture the fields from the second collection.

    Template.Infos.onRendered(function() {

        $('#txtName').val(Meteor.user().profile.name);
        $('#txtEmail').val(Meteor.user().emails[0].address);

});

These 2 work great.

But I don´t know how to query the infos from the collection 'dbInfos', which is not the 'users' collection. Obviously Meteor.user().country does not work, because it is not in the 'users' collection. Maybe a find({}) query? However, I don´t know how to write it.

$('#txtCountry').val( ***query function***);

Regarding the structure of 'dbInfos': Every object has an _id which is equal to the userId plus more fields like country, city etc...

{
"_id": "12345",
"country": "countryX",
"city": "cityY"
}

Additionally, how can I guarantee that nothing is presented, when the field in the collection is empty? Or is this automatic, because it will just return an empty field?

Edit

I now tried this:

dbInfos.find({},{'country': 1, '_id': 0})

I think this is the correct syntax to retrieve the country field and suppress the output of the _id field. But I only get [object Object] as a return.

Upvotes: 0

Views: 8680

Answers (1)

zim
zim

Reputation: 2386

you're missing the idea of a foreign key. each item in a collection needs a unique key, assigned by mongo (usually). so the key of your country info being the same as the userId is not correct, but you're close. instead, you can reference the userId like this:

{
  "_id": "abc123",
  "userId": "12345",
  "country": "countryX",
  "city": "cityY"
}

here, "abc123" is unique to that collection and assigned by mongo, and "12345" is the _id of some record in Meteor.users.

so you can find it like this (this would be on the client, and you would have already subscribed to DBInfos collection):

let userId = Meteor.userId();
let matchingInfos = DBInfos.find({userId: userId});

the first userId is the name of the field in the collection, the second is the local variable that came from the logged in user.

update:

ok, i think i see where you're getting tripped it. there's a difference between find() and findOne().

find() returns a cursor, and that might be where you're getting your [object object]. findOne() returns an actual object.

for both, the first argument is a filter, and the second argument is an options field. e.g.

let cursor = DBInfos.find({
    userId: Meteor.userId()
  },
  {
    fields: {
      country: 1
    }
  });

this is going to:

  1. find all records that belong to the logged in user
  2. make only the country and _id fields available
  3. make that data available in the form of a cursor

the cursor allows you to iterate over the results, but it is not a JSON object of your results. a cursor is handy if you want to use "{{#each}}" in the HTML, for example.

if you simply change the find() to a findOne():

let result = DBInfos.findOne({ /** and the rest **/

... now you actually have a JSON result object.

you can also do a combination of find/fetch, which works like a findOne():

let result = DBInfos.find({
    userId: Meteor.userId()
  },
  {
    fields: {
      country: 1
    }
  }).fetch();

with that result, you can now get country:

let country = result.country;

btw, you don't need to use the options to get country. i've been assuming all this code is on the client (might be a bad assumption). so this will work to get the country as well:

let result = DBInfos.findOne({userId: Meteor.userId()});
let country = result.country;

what's going on here? it's just like above, but the result JSON might have more fields in it than just country and _id. (it depends on what was published).

i'll typically use the options field when doing a find() on the server, to limit what's being published to the client. on the client, if you just need to grab the country field, you don't really need to specify the options in that way.

in that options, you can also do things like sort the results. that can be handy on the client when you're going to iterate on a cursor and you want the results displayed in a certain order.

does all that make sense? is that what was tripping you up?

Upvotes: 1

Related Questions