Querying array of ObjectIds using mongoose - mongodb

The users table contains an items array which is just a collection of Item ObjectId's.
Users
{
state: 'active',
items: [ObjectId("4ecc05e55dd98a436ddcc47c"), ObjectId("4ecc05e55dd98a436ddcc47d")]
}
Items
{
name: 'weapon',
creator: 'mark'
}
I want to write a query that finds all users which have an item with creator 'mark'. Is that possible in one query? I tried something like this but it does not work.
{
'items.creator': 'mark
};

Firstly, you need to have the items collection either as embedded or reference. With this structure in mind, we can write the query as
db.Users.find({"items.creator" : 'mark'})

Related

Search for data in an array in a document in mongo

I have a collection organization with field
users: [
{
"user_id":"1",
"role":"1"
},
{
"user_id":"2",
"role":"2"
}]
and another collection users with fields
{
{"user_id":1},
{"user_id":2},
{"user_id":3},
{"user_id":4}
}
I need to display all users with user id present in the users array in the organizations collection. What is the best way to implement this?
if you just want to display the user_id of the users in the organization you have to unwind users field and do the project on user_id field like below.
collection.aggregate([{"$unwind","$users"},{"$project":{"user_id":"$users.user_id"}}])
db.myDbCollection.find({}, {"user_id": 1});
can use this statement to find data from your collection.

Order meteor find results by index in array

I have two collections in a Meteor project, loosely created like this:
ItemContainer.insert({
title: title,
items: [],
});
Items.insert({
title: title,
});
Whenever a new Item is created it's id is added to the items array in an ItemContainer.
I also have a helper like this:
Template.body.helpers() {
items() {
const instance = Template.instance();
const containerId = instance.state.get("currentContainer");
const theseItems = ItemContainer.find({ _id: containerId}).items;
return Items.find({ _id: { $in: items } });
}
}
The issue is that I want to sort the items that I'm returning by their index in the items array. So when I generate a list of items in the browser then the item whose id is at items[0] gets displayed first, followed by items[1] and so on. Unfortunately I can't find a simple solution in the Mongo docs.
I can think of some ways to do that, like constructing an object by iterating over the items array and returning that, but I have to imagine there's a simpler way. It's also possible for the number of items to grow quite large, in theory thousands or tens of thousands.
Anybody know an easy way to sort by array index?
You can try to sort items in ascending order when finding through ItemContainer. So that items are returned correct order.
const theseItems = ItemContainer.find({ _id: containerId}).sort({"items.0": 1}).items;

Pushing into sub document array inside by element

I have mongo db collection that looks like this :
({
_id:id ,
createdAt: new Date(),
name:name,
friends : [{name:"tommy",children:[{name:"sarah",age:12}]}],
dogs : [{}]
});
I would like to be able to insert a new element in the friends array if the name doesnt exist and a children element to that new array.
If i'm adding a new friend named john with a child nathaly , i'd like the output to be
({
_id:id ,
createdAt: new Date(),
name:name,
friends : [{name:"tommy",children:[{name:"sarah",age:12}]},{name:"john",children:[{name:"natahly",age:20}]}],
dogs : [{}]
});
If friend tommy already exist i would like just the children to be added to the children array and the output to now be
({
_id:id ,
createdAt: new Date(),
name:name,
friends : [{name:"tommy",children:[{name:"sarah",age:12},{name:"newchild",age:99}]},{name:"john",children:[{name:"natahly",age:20}]}],
dogs : [{}]
});
I've tried so many things already it's impossible to list.
currently i'm trying a mix of everything
// if `friends` is `[]`, push the empty children firstly through addToSet
var bulk = Directory.rawCollection().initializeUnorderedBulkOp();
bulk.find({_id: id, 'friends.name': {$exists: false}}).updateOne(
{$addToSet: {friends: {name: name_var, children: []}});
Meteor.wrapAsync(bulk.execute)();
// then Since previous step create the children array for said friend only if it doesn't already exist i'm just trying to update said friend with the new child
Directory.update(
{ _id: id,"friends.name": name_var },
{ $push: { "friends.$.children": {name:"sarah",age:12}
}}})
(i've also tried with "friends.children" instead of "friends.$.children" but i just get a different error)
And this should cover my three case but i'm having issues and i'm wondering if i'm going the right way. Any of you guys have any idea because this should at least work to add the children but it doesn't..
Errors : MongoError: The field 'friends.0.children' must be an array but is of type Object in document {_id: "0"} # when friends.$.children"
MongoError: cannot use the part (Friends of Friends.childrens) to traverse the element when friends.children"
One way of doing it would be to,
Initialize the object you want to insert/update
The object can have multiple children inserted at once.
var obj = {name:"tommy",children:[{name:"ds",age:12},{name:"two",age:12}]};
Initialize the Bulk API.
The order of operations does not matter here.
var bulk = db.t.initializeUnorderedBulkOp();
Find and update only the children records that already have a sub document for the name.
use the $addToSet operator to maintain unique records, and $each to add more than one children at a time.
bulk.find({"friends.name":obj.name})
.update({$addToSet:{"friends.$.children":{$each:obj.children}}});
Find and update those which do not have a sub document.
$push the entire object if a document doesn't have one.
bulk.find({"friends.name":{$ne:obj.name}})
.update({$push:{"friends":obj}});
bulk.execute();

How can I query for a subdocument full of objects in Mongo?

So I have a document with an unknown number of objects in it, each with 2 properties. It's a collection of friend lists, and I'm trying to confirm if someone has a friend with a certain username before I allow a user to send a request. I'm keeping the list of friends in a subdocument, like this:
>>all the _id and other properties<<, "ownerFriends":[{"friendId":"an id goes here", "friendUsername": "username"}, {"friendId":"another id", "friendUsername":"username2"}]
I'm trying to do a query that will return username2 if given that as input, but I don't know how to do that with dot notation because I think you need to know the specific property to look for, and these are heterodox amounts of friend objects in the ownerFriends property.
If you want to select the ownerFriend object that has username as the friendUserName you can use the following selector (assuming your collection is called Friends):
Friends.find({
"ownerFriends.friendUsername": "username2"
}, {
fields: { "ownerFriends.$": 1}
});
You can find a detailed explanation of how to query an array of objects based on a property here:
http://www.curtismlarson.com/blog/2015/08/08/meteor-mongodb-array-property-selector/
In summary you have an object that contains keys, one of whose values is an array of objects. You can perform queries on the arrays using $elemMatch In your case:
MyCollection.find({ ownerFriends: { $elemMatch: { friendUsername: searchString }}});
Although I think you'll need to also query on the current user's _id. Not knowing the details of your collection, I can only speculate with:
MyCollection.find({ userId: Meteor.userId(), ownerFriends: { $elemMatch: { friendUsername: searchString }}});

Meteor: How do you populate a field from one collection into another collection with _id field?

In mongo I have a document that stores pending userId's in a collaborators object array and looks like this:
researchThread {
_id: 4374583575745756
pending: {
collaborators: [
{
userId: '13745845754745753'
},
{
userId: '23755845854745731'
},
{
userId: '33755845653741736'
}]
}
}
The userId is the _id field for the user from the users collection. Each user also has a name and an email field.
How can I populate the name and email fields from the user collection, into this document for each user in the researchThread.pending.collaborators object array? And also, will the populated data be reactive when used in the templates?
Loop through each collaborator, find the relevant user document by searching the users collection for the id, and update the researchThread document with that information.
The data will be reactive if the researchThread collection is a Meteor.Collection which you're drawing from in your templates.
However, why do you want to copy the user data? Why not just have Meteor query the users collection based on the researchThread userId when you need the data in the template?