How to do text search in mgo? - mongodb

I'm trying to search "efg" in field named "abc"
c.Find(bson.M{"$text": bson.M{"abc": "efg"}})
c is Collection object. I'm not getting any result. What am I doing wrong?

You are generating {$text:{abc:"efg"}}, but your query should look like this:
{$text:{$search:"efg"}}
So try updating your code to:
c.EnsureIndexKey("abc")
c.Find(bson.M{"$text": bson.M{"$search": "efg"}})
Keep in mind that to search with $text, you need to specify an index. Check out this document that explains how to use it: http://docs.mongodb.org/manual/reference/operator/query/text/

use $regex(option i for case insensitive)
example:
c.Find(bson.M{"abc": &bson.RegEx{Pattern: "efg", Options: "i"}})

Related

How to update all documents based on whether an array contains a specific element in pymongo?

I have been trying with this:
self.followersDbRef.update({'followersList':{'$elemMatch':{'$eq':userID}}},{'$addToSet':{'feed':postDict},'$set':{'_id':userID}},multi=True,upsert=True)
but to no avail.
Instead another document is created altogether.
It should be such that whenever I add a post all other users that follow me will get the post copied to their feed.
In mongoDB the basic query { key: "value" } matches both for exact match and for match within an array. So if your data looks like this:
{"key": "a"},
{"key": ["a", "b"]}
Then the following query will match both documents:
db.collection.find({"key": "a"})
With that in mind, this is probably what you're looking for:
self.followersDbRef.update(
{'followersList': userID},
{'$addToSet': {'feed':postDict},'$set':{'_id':userID}},
multi=True,
upsert=True
)
Also note that upsert means that if no match is found, a document will be inserted instead. If you do not want that to happen, you can remove upsert=True or change it to False.

How to search for a value that IS NOT equal to the speciefied value?

I am using MongoDB and I need a query to check of a value is NOT a certain value, I know how to search for a value like this:
db.getCollection('ships').find({"name": "MY BOAT"})
So lets say I need a query that finds the entries where name is not "MY BOAT"
I allready checked out the $NOT operator https://docs.mongodb.com/manual/reference/operator/query/not/
But don't understand how to apply it.
db.getCollection('ships').find( { name: { $ne: "MY BOAT" } } )
https://docs.mongodb.com/manual/reference/operator/query/ne/
follow the above url for more information
This can be accomplished with the $ne operator, so the query becomes:
db.getCollection('ships').find({"name": {$ne: "MY BOAT"}})
The credits for this answer go to #JohnnyHK

MongoDB check if value exists within array

I'm using MongoDB inside a twig framework. I'm trying to determine if the user has access to a certain module.
(a part of) my DB entry looks like:
_id: "579b50a4f5092761a20f4e71",
approvedModules: [
"examplemodule",
"examplemodule1",
"examplemodule2",
"examplemodule3"
],
My code looks like:
session.get('__AUTH_USER').find({ approvedModules : { '$in' : ["examplemodule"]}}, { '$exists' : true })
(the standard functions have to be in quotes).
I keeps returning false. I can only return the value if I use session.get('__AUTH_USER').approvedModules.0
I don't want to include the .0 because that might change.
What am I doing wrong?
Thanks in advance!
What am I doing wrong?
Many things. The worst one is using queries to database inside a template, but it is another problem.
You misunderstood purpose of the $in operator, which is used to match a field in the database to any element of array in the query.
To match any element of array in the collection to a single value you can do simple $eq:
session.get('__AUTH_USER').find({ approvedModules : "examplemodule"})
When you are using $in operator, you need to have 2 input arguments, the first one is the value for which you are checking the array, and the second one should be the array itself.
So, your bson element should look like this:
isModuleInArray : { '$in' : ["examplemodule","$approvedModules"] }

Get text words from query

I've read the MongoDB documentation on getting the indexes within a collection, and have also searched SO and Google for my question. I want to get the actual indexed values.
Or maybe my understanding of how MongoDB indexes is incorrect. If I've been indexing a field called text that contains paragraphs, am I right in thinking that what gets indexed is each word in the paragraph?
Either case I want to retrieve the values that were indexed, which db.collection.getIndexes() doesn't seem to be returning.
Well yes and no, in summary.
Indexes work on the "values" of the fields they are supplied to index, and are much like a "card index" in that there is a point of reference to look at to find the location of something that matches that term.
What "you" seem to be asking about here is "text indexes". This is a special index format in MongoDB and other databases as well that looks at the "text" content of a field and breaks down every "word" in that content into a value in that "index".
Typically we do:
db.collection.createIndex({ "text": "text" })
Where the "field name" here is "text" as you asked, but more importantly the type of index here is "text".
This allows you to then insert data like this:
db.collection.insert({ "text": "The quick brown fox jumped over the lazy dog" })
And then search like this, using the $text operator:
db.collection.find({ "$text": { "$search": "brown fox" } })
Which will return and "rank" in order the terms you gave in your query depending how they matched the given "text" of your field in the index on your collection.
Note that a "text" index and it's query does not interact on a specific field. But the index itself can be made over multiple fields. The query and the constraints on the "index" itself are that there can "only be one" text index present on any given collection otherwise errors will occur.
As per mongodb's docs:
"db.collection.getIndexes() returns an array of documents that hold index information for the collection. Index information includes the keys and options used to create the index. For information on the keys and index options, see db.collection.createIndex()."
You first have to create the index on the collection, using the createIndex() method:
db.records.createIndex( { userid: 1 } )
Queries on the userid field are supported by the index:
Example:
db.records.find( { userid: 2 } )
db.records.find( { userid: { $gt: 10 } } )
Indexes help you avoid scanning the whole document. They basically are references or pointers to specific parts of your collection.
The docs explain it better:
http://docs.mongodb.org/manual/tutorial/create-an-index/

How do I rename a nested key in mongodb

I want rename to rename my dict key in mongodb.
normally it works like that db.update({'_id':id},{$rename:{'oldfieldname':newfieldname}})
My document structure looks like that
{
'data':'.....',
'field':{'1':{'data':....},'2':{'data'...}},
'more_data':'....',
}
if i want to set
a new field in field 1 i do db.update({'_id':id},{$set:{'field.0.1.name':'peter'}})
for field two it is 'field'.1.2.name'
i thought with the rename it should be similar but it isn't ... (like $rename:{'field'.0.1': 2}
Here's a flexible method for renaming keys in a database
Given a document structure like this...
{
"_id": ObjectId("4ee5e9079b14f74ef14ddd2f"),
"code": "130.4",
"description": "4'' Socket Plug",
"technicalData": {
"Drawing No": "50",
"length": "200mm",
"diameter: "20mm"
},
}
I want to loop through all documents and rename technicalData["Drawing No"] to technicalData["Drawing Number"]
Run the following javascript in the execute panel in (the excellent) RockMongo
function remap(x){
dNo = x.technicalData["Drawing No"];
db.products.update({"_id":x._id}, {
$set: {"technicalData.Drawing Number" : dNo},
$unset: {"technicalData.Drawing No":1}
});
}
db.products.find({"technicalData.Drawing No":{$ne:null}}).forEach(remap);
The code will also run in a mongo shell
Your question is unclear but it seems you'd like to rename a field name within an array.
The short answer is you can't. As stated in the docs, $rename doesn't expand arrays to find a matching name. It only works on top level fields.
What you can do to simulate rename is by copying the field and its data to the new name, and then deleting the original field. You might also need a way to account for potentially concurrent writes if you have a lot of writes to that object/field.