Checking for the existence of objects with certain fields in pymongo - python-3.x

I need to check if an object exists in the database that has at least one matching field with a field from the dictionary
Pymongo
I have this, but it doesn't work:
import pymongo
client = pymongo.MongoClient()
users_db = client['UsersDB']
users_collection = users_db['users']
def check(collection, elements):
return bool(collection.find_one(filter={'$or' : [item for item in elements.items()]}))

You are on the right track but the query needs to be valid MQL. Try:
collection.find_one(filter={'$or' : [{k:{'$eq':v}} for k,v in elements.items()]})

Related

remove one object of a class from list of objects

I need to delete an object from the list of objects based on the condition.
In the selectDoctor method, I need to remove the object from the list in which its docid is equal to the given id and return the removed list.
class Doctor:
def __init__(self, docid, docname, deptname):
self.docid = docid
self.docname = docname
self.deptname = deptname
class Hospital:
def selectDoctor(id,doclist):
for i in range(0, len(doclist)):
if doclist[i].docid==id: //in this condition I need to remove that object from list
doclist.remove(i) //by removing like this it is showing error
return doclist
for i in range(5):
docid=int(input())
docname=input()
deptname=input()
doclist.append(Doctor(docid,docname,deptname)
id=int(input())
res=Hospital.selectDoctor(id,doclist)
print(res)
Using list in Python3, it,s easy to achieve this using following statements(you have at least three possibilities):
Remove by specifying the item index
doclist.pop(i)
OR
Remove by specifying the item(s) index(es) (also range of indexes also allowed e.g. del doclist[0:2] for removing first three items of given list) using the keyword del
del doclist[i]
Remove by specifying the item itself
doclist.remove(doclist[i])
Reference: https://docs.python.org/3.8/tutorial/datastructures.html
Feel free to upvote the answer after fixing your error...

How to Save all models changes in one query on Django

I try to modify many instance of some model (like User model), and this changes is different (I don't want to use update QuerySet method and not works for my scenario).
For example some user need to change first_name and some user need to change last_name and get users like : all_user = User.objects.all()
I think if I use save method for each instance after change, Django sent one query for save that!
How can I save all changes to database in one query instead of use foreach on models and save that one by one?
Given the comment from #iklinac, I would thoroughly recommend implementing django's own approach to bulk updates detailed here
It's quite similar to my original answer, below, but it looks like the functionality is now built in.
# bulk_update(objs, fields, batch_size=None)
>>> objs = [
... Entry.objects.create(headline='Entry 1'),
... Entry.objects.create(headline='Entry 2'),
... ]
>>> objs[0].headline = 'This is entry 1'
>>> objs[1].headline = 'This is entry 2'
>>> Entry.objects.bulk_update(objs, ['headline'])
Original answer
There's a package called django-bulk-update which is similar to bulk create which is builtin to django.
An example of where I use this, is part of an action in an admin class;
#admin.register(Token)
class TokenAdmin(admin.ModelAdmin):
list_display = (
'id',
'type'
)
actions = (
'set_type_charity',
)
def set_type_charity(self, request, queryset):
for token in queryset:
token.type = Token.Type.CHARITY
bulk_update(
queryset,
update_fields=['type', 'modified'],
batch_size=1000
)
Usage, taken from their readme;
With manager:
import random
from django_bulk_update.manager import BulkUpdateManager
from tests.models import Person
class Person(models.Model):
...
objects = BulkUpdateManager()
random_names = ['Walter', 'The Dude', 'Donny', 'Jesus']
people = Person.objects.all()
for person in people:
person.name = random.choice(random_names)
Person.objects.bulk_update(people, update_fields=['name']) # updates only name column
Person.objects.bulk_update(people, exclude_fields=['username']) # updates all columns except username
Person.objects.bulk_update(people) # updates all columns
Person.objects.bulk_update(people, batch_size=50000) # updates all columns by 50000 sized chunks
With helper:
import random
from django_bulk_update.helper import bulk_update
from tests.models import Person
random_names = ['Walter', 'The Dude', 'Donny', 'Jesus']
people = Person.objects.all()
for person in people:
person.name = random.choice(random_names)
bulk_update(people, update_fields=['name']) # updates only name column
bulk_update(people, exclude_fields=['username']) # updates all columns except username
bulk_update(people, using='someotherdb') # updates all columns using the given db
bulk_update(people) # updates all columns using the default db
bulk_update(people, batch_size=50000) # updates all columns by 50000 sized chunks using the default db

How to convert python dict to DictRow object

Hi I am writing unittest using pytest. But I am not able to mock few db functions. We are using psycopg2 for db connections and executions. Response of query returned from psycopg2 is of the type DictRow which can be accessed either by key or by index.
Ex:
response = ['prajwal', '23', 'engineer'] #Response of a query "select name, age , job from users"
>>>response[0]
'prajwal'
>>>response['name']
'prajwal'
I want to know is there any way by which we can covert dict/list to above mentioned type.
Looking at the source for psycopg2, creating a DictRow requires passing in a DictCursor object. However the only thing it uses from DictCursor appears to be an index and description attribute.
# found in lib\site-packages\psycopg2.extras.py
class DictRow(list):
"""A row object that allow by-column-name access to data."""
__slots__ = ('_index',)
def __init__(self, cursor):
self._index = cursor.index
self[:] = [None] * len(cursor.description)
The index looks like a dict with a mapping a key to an index. e.g.response['name'] = 0
The description looks like your dict that you want to convert.
If you're feeling hacky you could take advantage of duck typing and pretend you're passing in a cursor when you're just satisfying the requirements.
The only caveat is after we instantiate the DictRow, we need to populate it. Our fake cursor hack will take care of the rest.
from psycopg2.extras import DictRow
class DictRowHack:
def __init__(self, my_dict):
# we need to set these 2 attributes so that
# it auto populates our indexes
self.index = {key: i for i, key in enumerate(my_dict)}
self.description = my_dict
def dictrow_from_dict(my_dict):
# this is just a little helper function
# so you don't always need to go through
# the steps to recreate a DictRow
fake_cursor = DictRowHack(my_dict)
my_dictrow = DictRow(fake_cursor)
for k, v in my_dict.items():
my_dictrow[k] = v
return my_dictrow
response = {'name': 'prajwal', 'age': '23', 'job': 'engineer'}
my_dictrow = dictrow_from_dict(response)
print(my_dictrow[1])
print(my_dictrow['name'])
print(type(my_dictrow))

How to know what collections I have in Firestore using Python API

I am using Python to conect to a firestore database from a client.
The problem is that I don't know how to see what collections he has in the database:
from google.cloud import firestore
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore
cred = credentials.Certificate('credentials/credentials.json')
app = firebase_admin.initialize_app(cred)
db = firestore.client()
users_ref = db.collection(u'name_of_colection')
docs = users_ref.stream()
for doc in docs:
print(u'{} => {}'.format(doc.id, doc.to_dict()))
I have been looking how to get the name of the collections that he has but I didn't find anything that it was useful to me. I have also tried this:
cols = db.collections()
list_col = []
for col in cols:
list_col.append(col)
len(list_col)
I have obtained len = 6
Then I have done this for the different col in the list I have generated:
docs = list_col[5].stream()
data = []
for doc in docs:
data.append(doc.to_dict())
print(data)
This data print a dictionary with keys and values, but I don't know only get a list with the name of collections,
I think that you have to get the id from each collection (which is the collection name you are talking about
list_col = []
for col in collections:
list_col.append(col.id) // <-- add this please
print(list_col)
I hope it helps you
Any collection you see in fire base depends on your rights.
you can use
query = client.collection_group('mygroup')
or
query = client.collections()
It gives top hierarchy and you have to run multiple times to find the lowest document level.
query = client.collection_group('mygroup')
#param {string} collectionId Identifies the collections to query over. Every collection or subcollection with this ID as the last segment of its path will be included. Cannot contain a slash. #returns {Query} The created Query.
collections()[source]
List top-level collections of the client’s database.
Returns
iterator of subcollections of the current document.
Return type
Sequence[CollectionReference]
Simple solution:
import firebase_admin
from firebase_admin import firestore
app_options = {'projectId': 'test-project'}
default_app = firebase_admin.initialize_app(options=app_options)
db = firestore.client()
collection = db.collections()
list_col = []
for col in collection:
list_col.append(col.id)
print(list_col)

Mongoengine Link to Existing Collection

I'm working with Flask/Mongoengine-MongoDB for my latest web application.
I'm familiar with Pymongo, but I'm new to object-document mappers like Mongoengine.
I have a database and collection set up already, and I basically just want to query it and return the corresponding object. Here's a look at my models.py...
from app import db
# ----------------------------------------
# Taking steps towards a working backend.
# ----------------------------------------
class Property(db.Document):
# Document variables.
total_annual_rates = db.IntField()
land_value = db.IntField()
land_area = db.IntField()
assessment_number = db.StringField(max_length=255, required=True)
address = db.StringField(max_length=255, required=True)
current_capital_value = db.IntField
valuation_as_at_date = db.StringField(max_length=255, required=True)
legal_description = db.StringField(max_length=255, required=True)
capital_value = db.IntField()
annual_value = db.StringField(max_length=255, required=True)
certificate_of_title_number = db.StringField(max_length=255, required=True)
def __repr__(self):
return address
def get_property_from_db(self, query_string):
if not query_string:
raise ValueError()
# Ultra-simple search for the moment.
properties_found = Property.objects(address=query_string)
return properties_found[0]
The error I get is as follows: IndexError: no such item for Cursor instance
This makes complete sense, since the object isn't pointing at any collection. Despite trolling through the docs for a while, I still have no idea how to do this.
Do any of you know how I could appropriately link up my Property class to my already extant database and collection?
The way to link a class to an existing collection can be accomplished as such, using meta:
class Person(db.DynamicDocument):
# Meta variables.
meta = {
'collection': 'properties'
}
# Document variables.
name = db.StringField()
age = db.IntField()
Then, when using the class object, one can actually make use of this functionality as might be expected with MongoEngine:
desired_documents = Person.objects(name="John Smith")
john = desired_documents[0]
Or something similar :) Hope this helps!
I was googling this same question and i noticed the answer has changed since the previous answer:
According to the latest Mongoengine guide:
If you need to change the name of the collection (e.g. to use MongoEngine with an existing
database), then create a class dictionary attribute called meta on your document, and set collection to the
name of the collection that you want your document class to use:
class Page(Document):
meta = {'collection': 'cmsPage'}
The code on the grey did the trick and i could use my data instantly.

Resources