Given this Job object structure, where users is an array of user documents:
{
_id: "56228b5ba851623018f88ff7",
created: "2015-10-17T17:54:35.475Z",
active: true,
workOrders: [{
startDate: "2015-10-18T05:00:00.000Z",
name: "Test1",
users: [{...}]
},{
startDate: "2015-10-20T05:00:00.000Z",
name: "Test2",
users: [{...}]
}]
}
Why does this query work:
Job.find({
'workOrders.users._id' : userId,
'created' : { '$gte' : new Date('10/17/2015'), '$lt': new Date('10/25/2015')},
'active' : true
}).exec(cb);
But this one does not:
Job.find({
'workOrders.users._id' : userId,
'workOrders.startDate' : { '$gte' : new Date('10/20/2015'), '$lt': new Date('10/25/2015')},
'active' : true
}).exec(cb);
Initial thought is that workOrder.startDate is not of type date, but it is.
Is there some reason I cannot query the nested workOrder object this way? I'm just confused why I can query the created date property on the Job document, I can query the array of nested user documents in the workOrders array, but then this last query doesn't work.
Note, there are no errors thrown, it simply returns no results. Even if I expand the date range to definitely be inclusive of all dates such as 01/01/2000 to 01/01/2016 I get nothing.
Can you replace both startDate's with:
created: {
type: Date,
default: Date.now
},
...to establish whether you can add multiple dates to a document, and that your startDate code is not incorrect?
Related
I have 'Users' collection which has two columns, '_id' and 'userName', both of type string.
I want to add third column 'UserId' which will be UUID wrapping the id from _id column.
Tried few ways but without any success.
For example:
{
_id: "fe83f869-154e-4c26-a5db-fb147728820f",
userName: "alex"
}
I want it to be:
{
_id: "fe83f869-154e-4c26-a5db-fb147728820f",
userName: "alex",
UserId: UUID("fe83f869-154e-4c26-a5db-fb147728820f")
}
I tried something like:
db.Users_temp.update(
{},
{ $set: {"UserId": UUID("$_id") } },
false,
true
)
But it results in columns with value UUID("----")
Will appreciate any help.
Ok,
Found a solution to my problem.
db.Users_temp.find().forEach(function(user) {
db.Users_temp.update(
{"_id" : user._id},
{ "$set": {"UserId": UUID(user._id)} }
)
})
this will work
i am not sure why but this works only with set operation as an array rather than as a object
db.Users_temp.update({},[{$set: {'UserId': '$_id'}}])
My database schema is somewhat like
{
"_id" : ObjectId("1"),
"createdAt" : ISODate("2017-03-10T00:00:00.000+0000"),
"user_list" : [
{
"id" : "a",
"some_flag" : 1,
},
{
"id" : "b",
"some_flag" : 0,
}
]
}
What I want to do is get the document where id is b & some_flag for the user b is 0.
My query is
db.collection.find({
'createdAt': {
$gte: new Date()
},
'user_list.id': 'b',
'user_list.some_flag': 1
}).sort({
createdAt: 1
})
When I run the query in shell. It returns the doc with id 1(which it shouldn't as the value of some_flag for b is 0)
The thing happening here is,
the query 'user_list.id': user_id matches with the nested object where "id" : b
'user_list.some_flag': 1 is matched with some_flag of nested object where "id": a (as the value of some_flag is 1 here)
What modifications should I make to compare the id & some_flag for the same nested object.
P.S. the amount of data is quite large & using aggregate will be a performance bottleneck
You should be using $elemMatch otherwise mongoDB queries are applied independently on array items, so in your case 'user_list.some_flag': 1 will be matched to array item with id a and 'user_list.id': 'b' will match array item with id b. So essentially if you want to query on array field with and logic use $elemMatch as following:
db.collection.find({
'createdAt': {
$gte: new Date()
},
user_list: {$elemMatch: {id: 'b', some_flag: 1}} // will only be true if a unique item of the array fulfill both of the conditions.
}).sort({
createdAt: 1
})
you need to try something like :
db.collection.find({
'createdAt': {
$gte: new Date()
},
user_list: {
$elemMatch: {
id: 'b',
some_flag: 1
}
}
}).sort({
createdAt: 1
});
This will match only user_list entries where _id is b and someflag is 1
I'm trying to get all documents in a collection based on a subdocument array values. This is my data structure in the collection i'm seeking:
{
_id: ObjectId('...'),
name: "my event",
members:
[
{
_id: ObjectId('...'),
name: "family",
users: [ObjectId('...'),ObjectId('...'),ObjectId('...')]
},
{
_id: ObjectId('...'),
name: "work",
users: [ObjectId('...'),ObjectId('...'),ObjectId('...')]
}
]
}
I should point out that the schema of these objects are defined like so:
Events:
{
name: { type: String },
members: {type: [{ type: ObjectId, ref: 'MemberGroup' }], default:[] }
}
MemberGroup:
{
name: { type: String },
users: [{type: mongoose.Schema.Types.ObjectId, ref: 'User'}]
}
and of course User is just an arbitrary object with an id.
What i'm trying to fetch: i want to retrieve all events which has a specific user id in its member.users field.
i'm not sure if its event possible in a single call but here is what i've tried:
var userId = new mongoose.Schema.ObjectId('57d9503ef10d5ffc08d6b8cc');
events.find({members: { $elemMatch : { users: { $in: [userId]} } }})
this syntax work but return no elements even though i know there are matching elements (using robomongo to visualize the db)
So after a long search in stackoverflow i came across the good answare here:
MongoDB: How to find out if an array field contains an element?
my query changed to the following which gave me my desired result:
var userId = new mongoose.Schema.ObjectId('57d9503ef10d5ffc08d6b8cc');
events.find({}, {members: { $elemMatch : { users: { $eq: userId} } }})
notice the use of the second find parameter to specify the query limit instead of the first one (which is odd)
I'm working on an app based on mongodb and mongoose. One of my schemas has the following form:
var schema = new mongoose.Schema(
{
name: { type: String },
timestamp: { type: Number, default: Date.now },
// further properties
});
schema.index({ name: 1, timestamp: -1 });
I'd like to retrieve the newest object (i.e., largest timestamp) for a set of name-strings.
E.g., consider the set of names ['a','b']. How do I query the database such that I get returned a collection of objects that contains both, the newest entry where id=='a', and the newest entry where id=='b'?
[Update: The idea is to avoid having to query the database multiple times (i.e. once for each name).]
"How do I query the database such that I get returned a collection of objects that contains the newest where id=='a'"
db.collection.find({ name : 'a' }).sort({ timestamp : -1 })
"and the newest entry where id=='b'?"
db.collection.find({ name : 'b' }).sort({ timestamp : -1 }).limit(1)
I'm trying to run an aggregation statement in my mongo db. I have a document whose structure is (at least) as follows:
{
"_id": ObjectId,
"date": ISODate,
"keywordGroupId": NumberLong,
"ranking": NumberLong,
}
I would like to run an aggregation statement that aggregates the 'ranking' field for a given 'keywordGroupId' and a given 'date' interval.
I have been trying with the following aggregate command:
{
aggregate : "KeywordHistory",
pipeline : [
{ $match: { keywordGroupId: 75 , "$date": {$gte: ISODate("2013-01-01T00:00:00.0Z"), $lt: ISODate("2013-02-01T00:00:00.0Z")}} },
{ $group: { _id: { null }, count: { $sum: "$ranking" } } }
]
}
This command executes without errors and returns a result. If I try to change the value for the 'keywordGroupId' field, the command returns a different value, so I assume that the $match statement works for that field (NumberLong). Though, if I change the 'date' range and I specify a time interval for which I don't have any data in the database, it still returns a result (I would actually expect an empty result set). So I have to assume that the $match statement is ignoring the date interval specified.
Can anyone help me with this point?
Remove the $ prefix on the $date field of your $match:
{ $match: {
keywordGroupId: 75,
date: {$gte: ISODate("2013-01-01T00:00:00.0Z"), $lt: ISODate("2013-02-01T00:00:00.0Z")}
}},
You only use the $ prefix when the field name is used in a value, not as a key.
Sometimes ISodate does not works . so in Case if you want to match date using only "one" date the best way is:---
ex:-- Let a schema be:---
var storeOrder = new Schema({
store_name:{type:String, required:true},
date :{type:Date ,default:moment(new Date()).format('YYYY-MM-DD')},
orders : [{
vegetable : String,
quantity : Number,
price:Number
}]
});
mongoose.model('storeorder',storeOrder);
now to aggregate by matching date :--
storeOrder.aggregate([$match:{date :new Date("2016-12-26T00:00:00.000Z")} ])
**It is must to use new Date("2016-12-26T00:00:00.000z") instead of Date("2016-12-26T00:00:00.000z") because Date(your_date) !== new Date(your_date).
THANK YOU
The aggregate expects a Javascript Date Object and doesn't work otherwise.
new Date();
new Date(year, month, day);
Please note the month start with 0 and not 1 (Your January is 0 and December 11)