Create multiple collections in mongodb using PyMongo - mongodb

I am trying to create multiple collections in MongoDB using pymongo module as below. But its been failing.
import pymongo
client = MongoClient('localhost:27017')
mydb = client.tstdata # connect/create a db in mongodb
list1 = ["tst-1","tst-2","tst-3"] # list of collections to be created
for each_val in list1:
print (each_val)
col = mydb.each_val #create collection
col.insert_one({"name" : "test"})
Instead of creating multiple collections using values in 'each_val' variable, its just creating collection with "each_val" name; how can I fix the above error

Use the syntax:
col = mydb[each_val]
The drivers do their best to (sort of) match the mongo shell. So db.x.insert will insert into collection x rather than any variable named x as you have seen.

according to your code, you are creating each_val collection
you have to add collection name in square brackets in pymongo [ ]
from pymongo import MongoClient
client = MongoClient('localhost:27017')
mydb = client.tstdata # connect/create a db in mongodb
list1 = ["tst-1","tst-2","tst-3"] # list of collections to be created
for each_val in list1:
print (each_val)
col = mydb[each_val] #create collection
col.insert_one({"name" : test})

Related

Using ruamel.yaml to print out a list with individual elements singlequoted?

I have a dictionary with a few lists(contains a # of strings).
Example List:
hosts = ['199.168.1.100:1000', '199.168.1.101:1000']
When I try to print this out using ruamel.yaml, the elements show up as
hosts:
- 199.168.1.100:1000
- 199.168.1.101:1000
I want the results to be
hosts:
- '199.168.1.100:1000'
- '199.168.1.101:1000'
So I traversed through the list and created a new list with each element being a ruamel SingleQuotedString
S = ruamel.yaml.scalarstring.SingleQuotedScalarString
new_list = []
for e in hosts:
new_list.append(S(e))
hosts = new_list
When I print this out, I still end up printing the "hosts" list without any quotes. What am I doing wrong here?
In the following I assume you mean dumping to YAML when you indicate printing.
Your approach is in principle correct, as using the "global"
yaml.default_style = "'"
would also get the key hosts quoted, and that is not what you
want. Maybe you are not reassigning hosts to the actual datastructure that
you are dumping, because hosts is just the value of the key value pair you
are dumpiong.
The following:
import sys
import ruamel.yaml
S = ruamel.yaml.scalarstring.SingleQuotedScalarString
yaml = ruamel.yaml.YAML()
data = dict(hosts = [S(x) for x in ['199.168.1.100:1000', '199.168.1.101:1000']])
yaml.dump(data, sys.stdout)
will give what you want without problem:
hosts:
- '199.168.1.100:1000'
- '199.168.1.101:1000'

Retrieve stored image from mongodb using python

from pymongo import MongoClient
from bson.objectid import ObjectId
import numpy as np
import gridfs
import os,os.path
i=0
try:
for file in os.listdir("/Users/sarthakgupta/Desktop/sae/Images"):
if (file.endswith(".png") | file.endswith(".jpg")):
filename = "/Users/sarthakgupta/Desktop/sae/Images/"+file
datafile = open(filename,"rb")
thedata = datafile.read()
datafile.close()
c = MongoClient()
i=i+1
db = c.trial5
fs = gridfs.GridFS(db)
t = "class"+str(i)
stored = fs.put(thedata,filename=q)
except IOError:
print("Image file %s not found" %datafile)
raise SystemExit
I stored image in a mongo db . Now i want to retrieve those images from database by the filename and to store the image(or pixels) of same filename in an array or list. Suppose if there is 2 images with filename "class1",then they should be in one array.
Create your fs variable like before, and:
data = fs.get_last_version(filename).read()
You could also query for a list of files like:
from bson import Regex
for f in fs.find({'filename': Regex(r'.*\.(png|jpg)')):
data = f.read()
Also, a comment about your code: it's very slow to recreate the MongoClient and GridFS instances for every iteration of your loop. Create them once before you start looping, and reuse them.

Searching with multiple keys and "begins with"

What's the best way to perform the following type of search in a collection named "things":
mylist = ['lak', 'dodg', 'ang']
and the return could be:
["lake", "Lakers", "laky", "dodge", "Dodgers", "Angels", "angle"]
Would I need to perform a separate query for each?
To do this you want to use the mongodb command $in to search for all things that match with something in your array.
The command you would use would be:
db.things.find( {name: { $in: mylist }} )
But for this to work you want to be using regular expressions in your array, so you can either define them in the array, or if you want to maintain strings then the best thing to do it probably just create another array and loop through and create regex from the strings.
mylist = [/^lak/i, /^dodg/i, /^ang/i]
The ^ making it match only if it begins with the value, and the i at the end to make the search case insensitive.

mongodb $exists always returning 0

I have a database collection (named fols) like so:
{'followers':
{
'123':1
'123':2
'123':3
}
}
If I run the query (Using pymongo):
cursor = fols.find()
cursor.count()
>>3
Works fine. Now:
cursor = fols.find({'followers':{'123':1}})
cursor.count()
>>1
Again works fine. BUT if I try:
cursor = fols.find({'followers':{'123':{'$exists': True}}})
cursor.count()
>> 0
It returns 0 even though there are 3 records.
When you're not matching a complete object you need to use dot notation to use an operator against an embedded object. So in this case:
cursor = fols.find({'followers.123':{'$exists': True}})
Try the dot syntax:
cursor = fols.find({'followers.123': {'$exists': True}})
But also see my comment above. You can't have the same key more than once in a (sub-)document.

Perl hash of hash of lists from Net::LDAP to a 'filtered' list

The Net::LDAP module for Perl provides an Net::LDAP::Search object. Its as_struct method returns the structure below.
Multiple entries as
$entry{dn=...} =
ref {cn} = ref {name}
ref {l} = ref {city}
ref{mail} = ref {xxxxxx}
An example:
uid=pieterb,ou=People,dc=example,dc=org {key of first hash = dn in ldap}
uid=pieterb {key=uid}
cn=Pieter B. {key=cn}
uidNumber=1000 {key=uidNumber}
gidNumber=4000 {key=gidNumber}
uid=markc,ou=People,dc=example,dc=org {key of first hash = dn in ldap }
uid=markc {key=uid}
cn=Mark Cole {key=cn}
uidNumber=1001 {key=uidNumber}
gidNumber=4000 {key=gidNumber}
However, the interface uses UI::Dialog which expects a list in the format below (radiolist/checklist), with data coming from the attribute values in the LDAP server
list => [
'Pieter B.', ['uid=pieterb,ou=People,dc=example,dc=org',0],
'Mark Cole', ['uid=markc,ou=People,dc=example,dc=org',0],
'cn_value(openldap)',['dn_value',0],
'givenname_value(activedirectory)',['dn_value',0]
]
It is very hard to guess what you want, but I think it is a list of the LDAP attribute names versus their values.
You should look at Data::Dumper to examine and present the data structures you are dealing with.
You don't mention what to do if the data you get from the search contains multiple Distinguished Names, or multiple values for an attribute, but this code simply takes the first DN and the first value in lists of attribute values to generate a list of lists.
I have little doubt that this isn't exactly what you need, and if you specify your requirement better we will be able to help further.
my $data = $msg->as_struct;
my $entry = (values %$data)[0];
my #attributes = map {
$_, [$entry->{$_}[0], 0]
} keys %$entry;
$dialog->checklist(list => \#attributes);