I am total newbie to MongoDB. I was trying out basic stuff in mongo, when I encountered a problem. I searched for it, but not able to find any satisfactory answer.
I have a very simple collection named "users" having names and age of some persons. Below is output of db.users.find()
{ "_id" : ObjectId("566acc0442fea953b8d94a7e"), "name" : "gabriel", "age" : 22 }
{ "_id" : ObjectId("566acc0442fea953b8d94a7f"), "name" : "andy", "age" : 10 }
{ "_id" : ObjectId("566acc1342fea953b8d94a80"), "name" : "henry", "age" : 27 }
{ "_id" : ObjectId("566acc1342fea953b8d94a81"), "name" : "william", "age" : 19 }
{ "_id" : ObjectId("566acc3242fea953b8d94a82"), "name" : "sandra", "age" : 20 }
{ "_id" : ObjectId("566acc3242fea953b8d94a83"), "name" : "tom", "age" : 24 }
Now, I am trying to apply different projection on it. First two are:
db.users.find({}, {"name":1, "age":1})
{ "_id" : ObjectId("566acc0442fea953b8d94a7e"), "name" : "gabriel", "age" : 22 }
{ "_id" : ObjectId("566acc0442fea953b8d94a7f"), "name" : "andy", "age" : 10 }
{ "_id" : ObjectId("566acc1342fea953b8d94a80"), "name" : "henry", "age" : 27 }
{ "_id" : ObjectId("566acc1342fea953b8d94a81"), "name" : "william", "age" : 19 }
{ "_id" : ObjectId("566acc3242fea953b8d94a82"), "name" : "sandra", "age" : 20 }
{ "_id" : ObjectId("566acc3242fea953b8d94a83"), "name" : "tom", "age" : 24 }
db.users.find({}, {"name":0, "age":0})
{ "_id" : ObjectId("566acc0442fea953b8d94a7e") }
{ "_id" : ObjectId("566acc0442fea953b8d94a7f") }
{ "_id" : ObjectId("566acc1342fea953b8d94a80") }
{ "_id" : ObjectId("566acc1342fea953b8d94a81") }
{ "_id" : ObjectId("566acc3242fea953b8d94a82") }
{ "_id" : ObjectId("566acc3242fea953b8d94a83") }
are working just fine, but
db.users.find({}, {"name":0, "age":1})
Error: error: {
"$err" : "Can't canonicalize query: BadValue Projection cannot have a mix of inclusion and exclusion.",
"code" : 17287
}
is failing and giving error as shown above. I searched that problem may arise if there is conflicting conditions in projection, but I don't think there is something like that in my method call. Is there some rule like value of fields in find method should be either all ZERO or all ONE, but cannot be both. Please help.
If you want your query to return only the age, your projection must include only the fields you want to have. Not the one you don't want:
db.projection.find({}, {_id:0, age:1})
Exception for _id, you can specify to not include it.
Result
{
"age": 22
}
From the documentation:
A projection cannot contain both include and exclude specifications, except for the exclusion of the _id field. In projections that explicitly include fields, the _id field is the only field that you can explicitly exclude.
Related
I have a users collection in Mongo DB having 55L users. The collection is shared across 10 nodes.
There is a field "email" in the collection which stores the email address of the users.
I want to perform a text-based search on this field. I want to search for "mail" and the result should list all documents which have the substring "mail".
I tried with regex but it impacts performance due to collection size.
I tried creating a text index on "email" but it does not support partial search on tokens.
Collection example mentioned below
{ "_id" : ObjectId("5b90e5ffe34b5891eb4c32f6"), "email" : "anand#gmail.com" }
{ "_id" : ObjectId("5b90e64ee34b5891eb4c32f7"), "email" : "kumar.anand#hotmail.com" }
{ "_id" : ObjectId("5b90e65ae34b5891eb4c32f8"), "email" : "ankit#gmail.com" }
{ "_id" : ObjectId("5b90e661e34b5891eb4c32f9"), "email" : "rahul#rediff.com" }
{ "_id" : ObjectId("5b90e67de34b5891eb4c32fa"), "email" : "prachi#gmail.com" }
{ "_id" : ObjectId("5b90f0ab46ef1951e6afb822"), "email" : "bb#yahoo.com", "name" : "ankit" }
{ "_id" : ObjectId("5b965d4ad5bc80bda9885181"), "email" : "amit#gmail.com", "rating" : [ 5, 6 ] }
{ "_id" : ObjectId("5b965d56d5bc80bda9885182"), "email" : "amit33#gmail.com", "rating" : [ 2, 4 ] }
{ "_id" : ObjectId("5b965d60d5bc80bda9885183"), "email" : "amit11#gmail.com", "rating" : [ 12, 14 ] }
{ "_id" : ObjectId("5b966cf1f12e2344dc5942e5"), "email" : "avin11#gmail.com", "new_rating" : { "id" : [ 5, 6 ] } }
{ "_id" : ObjectId("5b966cfdf12e2344dc5942e6"), "email" : "avin22#gmail.com", "new_rating" : { "id" : [ 2, 4 ] } }
{ "_id" : ObjectId("5b966d06f12e2344dc5942e7"), "email" : "avin33#gmail.com", "new_rating" : { "id" : [ 12, 14 ] } }
{ "_id" : ObjectId("5b986afaf12e2344dc5942e8"), "email" : "Sachin#hotmail.com", "name" : "Sachin" }
Kindly suggest how to perform the search query
Hi and welcome to Stack overflow community..
I think you can still use a regex, but you should have an index on the email field to have better performance.
Read more about regex and indexes on mongo DB here: https://docs.mongodb.com/manual/reference/operator/query/regex/#index-use
I suggest using Explain Results to make sure your query uses the index you added.
Hope this helps.
I have collection Collection1 and I need to fetch an array like: [id1, id2, id3, ...] (array which consist of _id`s for every element in this collection). Is there any way to do this query with MongoDB tools ? Thank you!
You will have to use cursor.toArray() function on result of find having a projection document projecting only _id i.e ObjectId() value
MongoDB Enterprise > db.users.find().pretty()
{
"_id" : ObjectId("570e1d465a44f125ef156791"),
"name" : "Ritesh Talreja",
"age" : 22,
"gender" : "M"
}
{
"_id" : ObjectId("570e1e1d5a44f125ef156792"),
"name" : "Saloni",
"age" : 21,
"gender" : "F"
}
{
"_id" : ObjectId("570e1e485a44f125ef156793"),
"name" : "abcd",
"age" : 22,
"gender" : "M"
}
{
"_id" : ObjectId("570e28d45a44f125ef156794"),
"name" : "Saloni",
"age" : 21,
"gender" : "F"
}
{ "_id" : 123 }
MongoDB Enterprise > db.users.find({}, {_id:1}).toArray()
[
{
"_id" : ObjectId("570e1d465a44f125ef156791")
},
{
"_id" : ObjectId("570e1e1d5a44f125ef156792")
},
{
"_id" : ObjectId("570e1e485a44f125ef156793")
},
{
"_id" : ObjectId("570e28d45a44f125ef156794")
},
{
"_id" : 123
}
]
MongoDB Enterprise >
As an addition you can also use:
MongoDB Enterprise > db.users.distinct("_id")
[
123,
ObjectId("570e1d465a44f125ef156791"),
ObjectId("570e1e1d5a44f125ef156792"),
ObjectId("570e1e485a44f125ef156793"),
ObjectId("570e28d45a44f125ef156794")
]
MongoDB Enterprise >
I have this document structure, the property "Name" must be unique across all documents, as shown above:
{
"_id" : ObjectId("56686341d6389c004c689d5d"),
"Bosses" : {
"B1" : {
"_id" : NumberInt(1),
"Name" : "John"
},
"B2" : {
"_id" : NumberInt(1),
"Name" : "Mary"
}
}
}
{
"_id" : ObjectId("56686341d6389c004c689d6f"),
"Bosses" : {
"B1" : {
"_id" : NumberInt(1),
"Name" : "Mary" // should throw an error
}
}
}
It's possible to create a unique index with this structure?
Yes, you have to create a unique index on Bosses.Name. But then, You'll have to change a little bit your schema. Bosses should be an array:
{
"_id" : ObjectId("56686341d6389c004c689d6f"),
"Bosses" : [
{
"_id" : NumberInt(1),
"Name" : "Mary" // should throw an error
}
}
}
If you really need the B1, I suggest you add it into Bosses objects: "Code": "B1". But this might not be necessary, as you can access the index in your array by ...find({ "Bosses.0.Name" })
I have a collection ,this is one of it's docs :
{
"_id" : 1 ,
"first_name" : "john",
"phone" : [
{
"type" : "mobile",
"number" : "9151112233"
},
{
"type" : "home",
"city_code" : 51,
"number" : "55251544"
},
{
"type" : "mobile",
"number" : "9152425125"
}
]
}
I'm searching for "phones" that contain type "mobile" and show them.
I need something like this :
{
"number" : "9151112233",
"number" : "9152425125"
}
I write this query for that :
db.main.find({ _id : 1 , 'phone.type' : "mobile" },{'phone.number' : true , _id : false}).forEach(printjson)
I want to show only numbers that their types are mobile but this query show all to numbers because this single doc contain others too.
How can I fix it?
I'd use the aggregation framework along with the $unwind, $match and $project commands. This:
db.main.aggregate({$unwind:"$phone"},{$match:{"phone.type":"mobile"}},{$project:{"phone.number":1,"_id":0}})
produces this output:
{ "phone" : { "number" : "9151112233" } }
{ "phone" : { "number" : "9152425125" } }
which only matches the mobile numbers.
http://docs.mongodb.org/manual/aggregation/
C:\>mongo
C:\>C:\Programs\MongoDB\bin\mongo.exe
MongoDB shell version: 2.4.8
connecting to: test
Welcome to the MongoDB shell!
[test] 2014-02-26 17:09:35.933 >>> db.people.count();
9
[test] 2014-02-26 17:09:39.10 >>> db.people.find({})._addSpecial("$maxscan", 5);
{
"_id" : ObjectId("530e61be188483458f1edca7"),
"name" : "joe",
"random" : 0.7170755963306874
}
{
"_id" : ObjectId("530e61c2188483458f1edca8"),
"name" : "mark",
"random" : 0.6132313262205571
}
{
"_id" : ObjectId("530e61c7188483458f1edca9"),
"name" : "john",
"random" : 0.07292630313895643
}
{
"_id" : ObjectId("530e621c188483458f1edcaa"),
"name" : "allen",
"random" : 0.09901093109510839
}
{
"_id" : ObjectId("530e636f188483458f1edcab"),
"name" : "kevin",
"random" : 0.9719919066410512
}
{
"_id" : ObjectId("530e6375188483458f1edcac"),
"name" : "nicola",
"random" : 0.4626409418415278
}
{
"_id" : ObjectId("530e6428188483458f1edcad"),
"name" : "peter",
"random" : 0.8568310006521642
}
{
"_id" : ObjectId("530e642d188483458f1edcae"),
"name" : "tim",
"random" : 0.5209994465112686
}
{
"_id" : ObjectId("530e6437188483458f1edcaf"),
"name" : "joseph",
"random" : 0.6217151982709765
}
[test] 2014-02-26 17:09:51.76 >>>
I have 9 documents in this collection.
I am calling the find query above with
the option _addSpecial("$maxscan", 5).
And still, 9 documents are returned.
I was expecting 5 documents returned.
Why is it behaving this way?
I looked at the documentation here
http://docs.mongodb.org/manual/reference/operator/meta/maxScan/
but I don't think it provides any clues.
MongoDB is type-sensitive and case-sensitive, that means that you have to write the operator exactly as it is. You wrote like $maxscan but actually, according with the documentation is $maxScan.