Find records with a value outside a specific range in MongoDB - mongodb

I'm trying to find records in MongoDB that are created outside a specific period. The query to search for records inside a specific period is pretty straightforward:
db.test.find({"Published":{'$gt':"2011-08-02", '$lt':"2011-08-06"}})
So naturally, I tried this for "outside" a specific range:
db.test.find({'$not':{"Published":{'$gt':"2011-08-02", '$lt':"2011-08-06"}}})
But this returns an empty result, while there are definately records published then.
What query should I use instead? Can anyone help me? I'm using raw mongo queries.
Thanks in advance
--- UPDATE ---
I found that the following query works, but it doesn't look like the perfect solution:
db.test.find(
{'$or': [
{"Published":{'$lt':"2011-02-02"}},
{"Published":{'$gt':"2011-08-06"}}
]}
)
Is there a cleaner way to do it?

You are putting the $not in the wrong place. Try this:
db.test.find({"Published":{ $not:{$gt:"2011-08-02", $lt:"2011-08-06"} } })
For details, see the MongoDB docs about the $notoperator.
Edit as because of the comment this solution would not work:
> db.dates.find()
{ "_id" : ObjectId("5492d46ef6226b581c80c0a2"), "a" : 1, "date" : "2011-08-04" }
{ "_id" : ObjectId("5492d4e2f6226b581c80c0a3"), "a" : 2, "date" : "2011-08-07" }
> db.dates.find({date:{$not:{$gt:"2011-08-02",$lt:"2011-08-06"}}})
{ "_id" : ObjectId("5492d4e2f6226b581c80c0a3"), "a" : 2, "date" : "2011-08-07" }

Related

MongoDB Query: $all with nested property

Hello I need some help with MongoDB:
My Document has the following property (generated by an Map with spring):
"filter":{"billingAccount_id":["multisim5"],"simulate":["true"]}
and i'm trying to find the document with the this code (generated by spring)
query.addCriteria(Criteria.where("filter").all(getMapWithValues()));
which results in
"filter" : { "$all" : [{ "billingAccount_id" : ["multisim5"] }] }
but i'm getting no result. What's to do here?
Thanks for help in advance
You're applying $all on an object (filter) instead of an array (filter.billingAccount_id). Change your request (and method getMapWithValues) to get something like :
{"filter.billingAccount_id" : { "$all" : ["multisim5"] }}
BUT $all is used to find array that contains, at least, all values provided in query. Since there's an unique element in $all param, $all is useless here, and the following query output the same result :
{"filter.billingAccount_id" : "multisim5"}
EDIT : if you want to query array with exact match ("multisim5" and nothin else), use the following :
{"filter.billingAccount_id" : { "$eq" : ["multisim5"] }}

MongoDB Compound text search

I have a collection like this in my mongo database, let's say it's called taxonomic.
{
"_id" : ObjectId("5810e15a762a39b41912a131"),
"validName" : "Eros",
"idUser" : ObjectId("1")
}
{
"_id" : ObjectId("5810e15a762a39b41912a132"),
"validName" : "Eros",
"idUser" : ObjectId("2")
}
I've already created a compound index to be able to search for the two values I want, such as this.
db.taxonomic.createIndex({"idUser":1,"validName":1})
Now, I want to be able to search and get a return from it only when both of the parameters are found on the same document of the collections, here's my try:
db.taxonomic.find({$text:{$search:"Eros 2"}},{idUser:1,validName:1})
The problem with this method is that it will return any match of "Eros" OR "2", what I want is a return of the values when "Eros" AND "2" are matched in a document of the collection.
Thank you for any help!
I dont think you require a text Index for it if you only want specific string
db.taxonomic.find({"$or" : [{"validName" : "Eros"},{"validName" : "2"}]},{idUser:1,validName:1})

Mongo db : query on nested json

Sample json object :
{ "_id" : ObjectId( "55887982498e2bef5a5f96db" ),
"a" : "x",
"q" : "null",
"p" : "",
"s" : "{\"f\":{\"b\":[\"I\"]},\"time\":\"fs\"}" }
need all documents where time = fs
My query :
{"s":{"time" : "fs"}}
above returns zero products but that is not true.
There are two problems here. First of all s is clearly a string so your query cannot work. You can use $regex as below but it won't be very efficient:
{s: {$regex: '"time"\:"fs"'}}
I would suggest converting s fields to proper documents. You can use JSON.parse to do it. Documents can be updated based on a current value using db.foo.find().snapshot().forEach. See this answer for details.
Second problem is your query is simply wrong. To match time field you should use dot notation:
{"s.time" : "fs"})

MongoDB - How to find equals in collection and in embedded document

Gurus - I'm stuck in a situation that I can't figure out how I can query from the following collection "spouse", which has embedded document "surname" and check for equality with "surname" of this document:
{
"_id" : ObjectId("50bd2bb4fcfc6066b7ef090d"),
"name" : "Gwendolyn",
"surname" : "Davis",
"birthyear" : 1978,
"spouse" : {
"name" : "Dennis",
"surname" : "Evans",
"birthyear" : 1969
},
I need to query:
Output data for all spouses with the same surnames (if the surname of
one of the spouses is not specified, assume that it coincides with the
name of another)
I tried something like this:
db.task.find( {"surname" : { "spouse.surname" : 1 }} )
but it failed)
PLEASE PLEASE Guide me how I can achieve this any example/sample? based on this will be really helpful :-)
Thanks a lot!
You have three options.
Use $where modifier:
db.task.find({$where: 'this.spouse.surname === this.surname'})
Update all your documents and add special flag. After that you will be able to query documents by this flag. It's faster then $where, but requires altering your data.
Use MapReduce. It's quite complicated, but it allows you to do nearly anything.

Use MongoDB array as stack

Has anybody used MongoDB's Array type to implement a stack?
I know that I can append to an Array like so:
db.blogposts.update( {_id:5}, {$push: {comments: {by: "Abe", text:"First"}}})
Here, the end of the array is the top of the stack... I don't see a way to implement this with the top of the stack at the zero'th index, but I'd love to be wrong.
And I know that I can peek at the last value of the the array like so:
db.blogposts.find( {_id:5}, {comments: {$slice:-1}})
With an implementation like this, can I "peek" at the top of the stack in a MongoDB update statement? That would give me the semantic, "push this item on the stack if the top of the stack is X". I need this to be an atomic operation!
Any advice appreciated. Thanks!
Unfortunately, there is currently no way to do this exactly as you have described.
As Chris Shain pointed out, https://jira.mongodb.org/browse/SERVER-2191 - "$push() to front of array" and similarly https://jira.mongodb.org/browse/SERVER-1824 - "Support for inserting into specific array index" would help, but these features are currently not slated for a specific release version.
As a possible work-around, you could add a field named "lastElement" (or equivalent) to your document, which contains a copy of the last element pushed to the array. In your update statement, you could then query against the "lastElement" value, and if it matches, simultaneously set it to the new value and push the same value to the array in a single, atomic operation.
For example:
> db.blogposts.save({_id:5, comments:[{by: "Abe", text:"First"}], lastElement:{by: "Abe", text:"First"}})
> db.blogposts.find().pretty()
{
"_id" : 5,
"comments" : [
{
"by" : "Abe",
"text" : "First"
}
],
"lastElement" : {
"by" : "Abe",
"text" : "First"
}
}
> db.blogposts.update({"lastElement.text":"First"}, {$set:{lastElement:{by: "Joe", text:"Second"}}, $push:{comments:{by: "Joe", text:"Second"}}})
> db.blogposts.find().pretty()
{
"_id" : 5,
"comments" : [
{
"by" : "Abe",
"text" : "First"
},
{
"by" : "Joe",
"text" : "Second"
}
],
"lastElement" : {
"by" : "Joe",
"text" : "Second"
}
}
>
As an alternative, you may consider the strategy outlined in the "Update if Current" section of the "Atomic Operations" documentation: http://www.mongodb.org/display/DOCS/Atomic+Operations
I realize these are work-arounds and not ideal solutions. Hopefully the above will help you to accomplish your goal, or at least provide some food for thought for you to come up with a different solution. If you do, please share it here so that any members of the Community who may be experiencing similar issues may have the benefit of your experience. Thanks.
Looks like as of mongoDB v2.6, this is now supported via the $position operator: http://docs.mongodb.org/manual/reference/operator/update/position/
db.blogposts.update(
{_id:5}
, {$push:
{comments:
{$each: {by: "Abe", text:"First"}
, $position:0 }
}
}
);