compare multiple value in same document in mongodb - mongodb

My question was, how to find all title of the releases contains the artist name
Here is the 2 Documents for just an example:
`{"release" : {"title" : "DEF day",
"artists" : {"artist" : {"role" : "1","name" : "DEF"}}}
}
{ "release" : {"title" : "XYZ day",
"artists" : {"artist" : {"role" : "1","name" : "KYC"}}}
}`
when i run this following query:
`db.test.find({$where:
"this.release.title.indexOf(this.release.artists.artist.name) > -1"
})`
I get the result "DEF day", so it works excellent!!
BUT, once i run this query to my original data(same format like above) i get this:
`error: {
"$err" : "TypeError: Object 30 has no method 'indexOf'\n at _funcs1 (_funcs1:1:49) near 'his.release.artists.a' ",
"code" : 16722
}`
My collection is big (8GB+).
Just looking at the above error, can anyone tell what may be the problem with the above query? your answer is appreciated. please.

The problem is in the data itself. Somewhere you have a document, where the title field is not String, thus invoking indexOf on the whole data, on that particular document you get the error.
One thing you can do to solve this problem is first of all find that erroneous document. To do that you will need to run a simple query.
MongoDB has the $type operator, which matches fields by their type. And here is the list of all available BSON types a MongoDB document field can have.
The id of String BSON type is 2, thus you need all the documents that have type of title field not equal to 2.
find({field: {$not: {$type: <BSON type>}}}))
After finding the document(s), you may fix or remove them.

Related

Find doc from field having all specified words

I've problem to find the good document search request do find all documents containing in their 'name' field all the specified values.
I've this document:
{
"_id" : ObjectId("607c1caa4b2964d0185301ff"),
"nb" : 1,
"name" : "mini computer 24GB"
}
When I run the following find request...
db.getCollection('test').find({"$text":{$search:'computer dummy'}})
... the document is returned. An OR is done but I want a AND operation. Should I use a list of $and ?
Many thanks
Ok I found. each word must be in quotes as this:
db.getCollection('test').find({$text:{$search:"\"computer\" \"24GB\""}})
Not really intuitive!

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"})

Search full document in mongodb for a match

Is there a way to match a value with every array and sub document inside the document in mongodb collection and return the document
{
"_id" : "2000001956",
"trimline1" : "abc",
"trimline2" : "xyz",
"subtitle" : "www",
"image" : {
"large" : 0,
"small" : 0,
"tiled" : 0,
"cropped" : false
},
"Kytrr" : {
"count" : 0,
"assigned" : 0
}
}
for eg if in the above document I am searching for xyz or "ab" or "xy" or "z" or "0" this document should be returned.
I actually have to achieve this at the back end using C# driver but a mongo query would also help greatly.
Please advice.
Thanks
You could probably do this using '$where'
db.mycollection({$where:"JSON.stringify(this).indexOf('xyz')!=-1"})
I'm converting the whole record to a big string and then searching to see if your element is in the resulting string. Probably won't work if your xyz is in the fieldnames!
You can make it iterate through the fields to make a big string and then search it though.
This isn't the most elegant way and will involve a full tablescan. It will be faster if you look through the individual fields!
While Malcolm's answer above would work, when your collection gets large or you have high traffic, you'll see this fall over pretty quickly. This is because of 2 things. First, dropping down to javascript is a big deal and second, this will always be a full table scan because $where can't use an index.
MongoDB 2.6 introduced text indexing which is on by default (it was in beta in 2.4). With it, you can have a full text index on all the fields in the document. The documentation gives the following example where a text index is created for every field and names the index "TextIndex".
db.collection.ensureIndex(
{ "$**": "text" },
{ name: "TextIndex" }
)

Unable to get the value of a MongoDB key

2 days old to Mongo, so bear with me.
I have a collection from which, I only want to retrieve specific values contingent to another key existing in the MongoDB environment.
Here is what I am doing:
db.results.find({'someKeyThatShouldExist':{$exists:true}}, {"parentKey.childKey.theKeyWoseValueIwant":1}
This yields data in the following format for me:
{ "_id" : ObjectId("532a2c2b6803fa486b8b456a"), "parentKey" : { "childKey" : { "theKeyWhoseValueIWant" : 102982577 }}}.....
Now, all I really want is the value 102982577, not everything else.
How can I do this ?
You can suppress the _id by adding _id:0 to the projection criteria.
db.results.find(
{"someKeyThatShouldExist":{$exists:true}},
{_id:0, "parentKey.childKey.theKeyWoseValueIwant":1}
)
To get just the value, you could do something like:
db.results.find(
{"someKeyThatShouldExist":{$exists:true}},
{_id:0, "parentKey.childKey.theKeyWoseValueIwant":1}
)[0].parentKey.childKey.theKeyWoseValueIwant

are the following mongodb queries equivalent?

so i have the below query that does NOT return anything when it should.
db.food.find({ingredient : {name : {$ne : "Kahlua"}}}); //empty data
However, what i think is its equivalent does output the correct info:
db.food.find({"ingredient.name" : {$ne : "Kahlua"}}); //gives correct data
I tried this using the BrowserShell for the above 2 queries, and it hasn't given me much problem for simple functions and queries.
No, they are not the same.
db.food.find({"ingredient.name" : {$ne : "Kahlua"}});
is saying "find where the ingredient name is not equal to Kahlua", whereas...
db.food.find({ingredient : {name : {$ne : "Kahlua"}}});
is saying "find where the ingredient sub object consists of a name property only, where that name is not equal to Kahlua". So in this case you're actually performing a search on the whole subject.
Probably far better explained here - dot notation vs subobjects