Limiting embedded document size - mongodb

I have user schema for MongooseJS with embedded document photos by PhotoSchema:
var UserSchema = new Schema({
email : { type : String, index : 'unique', set: toLower }
, login : { type : String, index : 'unique' }
, password : { type : String }
, salt : { type : String }
, photos : [ PhotoSchema ]
, name : { type : String }
});
When I retreive one user, how can I limit quantity of photos in result set?
Or should I retrive all photos that user have (even if there is a million)?

You can't retreive users with limited quantity of photos, but you can:
1.Load user(s) without photos first:
db.users.find( { _id: 1 }, { photos : 0 } );
2.Load just user photos thats you need:
db.users.find({}, {photos:{$slice: [20, 10]}}) // skip 20, limit 10
Documentation

Related

Referencing for mongoose

i'm currently trying to reference a collection called items with the structure below
packageSchema = schema({
recipient: String,
contents: [{item :{type: mongoose.Schema.Types.ObjectId,
ref: 'items', required : true}, amount: String}]
Below is my code for getting one package via its id
getOnePackage : function(id,callback)
{
packageModel.findById(id,callback)
.populate('contents')
}
So when i call the above function i'm expecting to get this result
{
recipient : Dave
contents : [
{item : {
_id:5d2b0c444a3cc6438a7b98ae,
itemname : "Statue",
description : "A statue of Avery"
} ,amount : "2"},
{item : {
_id:5d25ad29e601ef2764100b94,
itemname : "Sugar Pack",
description : "Premium Grade Sugar From China"
} ,amount : "5"},
]
}
But what i got from testing in Postman is this :
{
recipient : Dave,
contents : []
}
May i know where did it went wrong? And also how do i prevent mongoose from automatically insert an objectId for every single element in the contents array....
Because element in contents array is object with item field so your populate should be:
.populate('contents.item')

Mongodb query use skip and limit function in first N documents

Can we make query which enable us to use skip and limit in first N documents?
Ex :
Suppose there are nearly 500 documents in a collection called teachers.
I want a query which restrict me to read first 300 documents only.
If I use skip(300) in that query it should display null.
db.teachers.find().pretty()
{
id : 1,
name : "teach001"
},
{
id : 2,
name : "teach002"
},
{
id : 3,
name : "teach003"
},
{
id : 4,
name : "teach004"
},
{
id : 5,
name : "teach005"
},
{
id : 6,
name : "teach006"
},
{
id : 7,
name : "teach007"
},
{
id : 8,
name : "teach008"
},
{
id : 9,
name : "teach009"
},
{
id : 10,
name : "teach0010"
}
db.teachers.find({some query here to restrict access first 5 documents only }).skip(5).limit(5).pretty()
Aggregation
I don't think there is a way to do exactly what you are requesting. If you are open to using the aggregation framework, it can be accomplished easily.
db.teachers.aggregate([{$limit: 5}, {$skip: 5}])
View
If you are open to creating a view, you could even create a view that enforces the limit
db.createView('limitedTeachers', 'teachers', [{$limit: 5}])
Then you can use find on the view:
db.limitedTeachers.find({}).skip(5)
Two finds
If you cannot use aggregation, you have the option of using 2 finds in your query. First, find the n number of Object IDs. Then, limit your second query to only those Object IDs.
var ids = [];
db.teachers.find({}, {_id: 1}).limit(5).forEach(function(doc){
ids.push(doc._id);
});
db.teachers.find({ _id: {$in: ids} }).skip(5)
Or as the same type of query but closer to the format you had in your question
db.teachers.find({$or: db.teachers.find({}, {_id: 1}).limit(5).toArray()}).skip(5)

Find the documents in mongoose whose array fields exactly match

I'm using Mongoose and have a schema like this:
var chat = new mongoose.Schema({
chatId : String,
members : [{
id : String,
name : String
}]
});
Suppose I have two chat document like this
{
chatId : 'Edcjjb',
members : [
{
id : 'a1',
name : 'aaa'
},
{
id : 'b1',
name : 'bbb'
}
]
}
{
chatId : 'Fxcjjb',
members : [
{
id : 'a1',
name : 'aaa'
},
{
id : 'b1',
name : 'bbb'
},
{
id : 'c1',
name : 'ccc'
}
]
}
I want to find all those documents which have only specfied members Id.
For example, if I specify a1 and b1
then only the first document should be retrieved as the second document contains id c1 as well.
And if I specifiy a1,b1,c1
then only second document should be specified.
Please tell me how to do this in mongoose
You can specify a clause on the array size, like
{ members : { $size : 2 } } in your first example and
{ members : { $size : 3 } } in the second one.
Can that work for you?
EDIT: I should also mention that the other part of the query should be
{ "members.id": { $all: [ "a1" , "b1" ] } }
and, for the second example,
{ "members.id": { $all: [ "a1" , "b1", "c1" ] } }

Meteor.users : $addToset in Profile [nested object]

Each time a user subscribe to a "street" or another "user" I want to add their Id to a nested object in The profile of the current User.
I have try the following with different results :
Meteor.users.update(Meteor.userId(), {
$addToSet: {
'profile.subscription': { Street : streetDis
}
}
})
This update the profile , but create an entry into the array each time :
Profile.subscription[0] : Street : "eziajepozjaoeja"
Profile.subscription[1] : Street : "eezapoezkaejz"
Profile.subscription[2] : User : "akzejpazjepza"
The architecture I want would be as follow :
Profile.subscription.Street[0] : "eziajepozjaoeja"
Profile.subscription.Street[1]:"eezapoezkaejz"
Profile.subscription.User[0]: "akzejpazjepza"
So I try :
Meteor.users.update(Meteor.userId(), {
$addToSet: {
'a.profile.last.Adress': "akzejpazjepza"}
}
)
Which return : update failed: Access denied
Meteor.users.update(Meteor.userId(), {
$addToSet: {
'a.profile': { last: {Adress : "akzejpazjepza"}}
}
})
This would also return : update failed: Access denied
If you want profile.subscription.streets and profile.subscription.users to be each be an array of ids, then you should update the user's document like this:
Meteor.users.update(Meteor.userId(), {
$addToSet: {
'profile.subscription.streets': streetId,
'profile.subscription.users': userId
}
});

mongodb select using association

I have two collections, user_logs and users, user_logs documents have user_id field so I need some data from user_logs but in the same query I want to check if some other field from user related to the current user_log is empty. How should I do this?
A query can only access one collection at a time. Mongodb doesn't support joins.
They that's why they recommend that you embed the referenced data inside the document.
If the logs documents for each user isn't too big, then you can change the embed that info inside the user collection.
Giving you something like this.
Embedded User Collection:
{
user_id : "uid1",
logs : [
{ message : "Error: System shutdown", date : "2014-11-11" },
{ message : "Error: System shutdown", date : "2014-11-13" }
]
}
However, if you want to keep your current structure then you're going to have to perform two queries to find related info between the users and user_logs collections.
Example
db.user_logs.insert([
{ _id : "ul1", log : "code 1", user_id : "u1" },
{ _id : "ul2", log : "code 2", user_id : "u1" }
]);
db.users.insert([
{ _id : "u1", name : "bob", user_logs_id : "ul1" },
{ _id : "u2", name : "smith", user_logs_id : "ul2" }
]);
var userId = db.user_logs.findOne({}).user_id;
db.users.findOne({ _id : userId })
//outputs
{ "_id" : "u1", "name" : "bob", "user_logs_id" : "ul1" }