PyMongo - ชื่อจะต้องเป็นตัวอย่างของ Str

ฉันกำลังพยายามอ่านและเขียนจากฐานข้อมูลบน MongoDB Atlas และแม้ว่าฉันจะสามารถอ่านข้อมูลจากคอลเลกชันของฉันได้ดี แต่ความพยายามใดๆ ในการเขียนไปยังคอลเลกชันจะทำให้ PyMongo ยกข้อยกเว้น 'ชื่อต้องเป็นอินสแตนซ์ของ str'

ฉันเดาว่านี่เป็นการอ้างอิงถึงวัตถุ MongoClient แต่สิ่งนั้นคือฉันกำลังใช้สตริงการเชื่อมต่อ ใครสามารถช่วยฉันด้วยสิ่งที่ฉันทำผิด?

รหัสของฉันเป็นดังนี้: (ฉันมีความคิดเห็นมากมายเพื่อช่วยให้ฉันเข้าใจดีขึ้น ดังนั้นโปรดแก้ตัวที่ไม่กระชับ)

def setattributes(self, rowdict):
        """ a function to create a user. Assumes that only a data
        dict is provided. strips everything else and updates.
         what the data dict contains is your problem.
        """
        with UseDatabase(self.dbconfig) as db:
            collection = db.database[self.tablename]
            locationdict = {    #create a corresponding location entry
            'email' : rowdict['email'],
            'devstate' : 0,
            'location' : {
            'type': 'Point',
            'coordinates' : [ 0, 0 ]
            },
            'lastseen' : datetime.now()
            }
            try:
                res = db.insertdata(collection, rowdict) #insert user data
            except Exception as e:
                print("Error adding user to DB : %s" % e)
                return False  # if you cant insert, return False
            try:  
                loccollection = db.database[self.locationtable]
                resloc = db.insertdata(loccollection, locationdict)
            except Exception as e: # if the status update failed
                db.collection.remove({'email' : rowdict['email']}) 
                #rollback the user insert - atomicity
                return False
        return True

รหัสฐานข้อมูลของฉันเป็นดังนี้:

class ConnectionError(Exception):
    pass

class CredentialsError(Exception):
    pass

class UseDatabase:
    def __init__(self, config: dict):
        self.config = config

    def __enter__(self, config = atlas_conn_str):
        try:
            self.client = MongoClient(config)
            self.database = self.client['reviv']
            return self

        except:
            print("Check connection settings")
            raise ConnectionError

    def __exit__(self, exc_type, exc_value, exc_traceback):
        self.client.close()

    def insertdata(self, collection, data):
        post = data
        post_id = self.database[collection].insert_one(post).inserted_id
        return post_id

    def getdetails(self, collection, emailid):
        user = collection.find_one({'email' : emailid}, {'_id' : 0})
        return user

person kilokahn    schedule 01.10.2017    source แหล่งที่มา


คำตอบ (1)


ใน "setattributes()" ของคุณ คุณเข้าถึงอินสแตนซ์ pymongo Collection ตามชื่อ:

collection = db.database[self.tablename]

จากนั้นใน "insertdata()" คุณพยายามทำสิ่งเดียวกันอีกครั้ง แต่ตอนนี้ "collection" ไม่ใช่สตริง แต่เป็นอินสแตนซ์ของ Collection:

post_id = self.database[collection].insert_one(post).inserted_id

ให้ทำดังนี้:

post_id = collection.insert_one(post).inserted_id

อย่างไรก็ตาม ฉันเห็นว่าคุณได้เขียนโค้ดบางส่วนเพื่อให้แน่ใจว่าคุณสร้างและปิด MongoClient สำหรับการดำเนินการแต่ละรายการ สิ่งนี้ซับซ้อนโดยไม่จำเป็นและจะทำให้แอปพลิเคชันของคุณช้าลงอย่างมากโดยต้องมีการเชื่อมต่อใหม่สำหรับการดำเนินการแต่ละครั้ง ดังที่คำถามที่พบบ่อยกล่าวไว้, "สร้างไคลเอนต์นี้หนึ่งครั้งสำหรับแต่ละกระบวนการ และนำมาใช้ซ้ำสำหรับการดำเนินการทั้งหมด การสร้างไคลเอนต์ใหม่สำหรับแต่ละคำขอถือเป็นข้อผิดพลาดทั่วไป ซึ่งไม่มีประสิทธิภาพมากนัก"

ฉันขอแนะนำให้คุณลบคลาส UseDatabase ของคุณ ทำให้ MongoClient เป็นตัวแปรโกลบอลของโมดูล และใช้ MongoClient โดยตรง:

client = MongoClient(atlas_conn_str)
db = client[locationtable]

class C:
    def setattributes(self, rowdict):
        collection = db[self.tablename]
        # ... make rowdict as usual, and then:
        res = collection.insert_one(rowdict)

รหัสนี้ง่ายกว่าและจะทำงานเร็วขึ้นมาก

person A. Jesse Jiryu Davis    schedule 01.10.2017
comment
ขอบคุณมากข้อเสนอแนะของคุณทำให้มันได้ผล ฉันยังรับคำแนะนำของคุณเกี่ยวกับการย้ายคลาสฐานข้อมูลออกและดำเนินการเชื่อมต่อในเธรดหลักด้วย - คลาสนี้เป็นส่วนที่เหลือจากแอปพลิเคชันเวอร์ชันก่อนหน้าของฉันที่ฉันใช้ MariaDB พร้อมการรวมการเชื่อมต่อ ขอบคุณมากอีกครั้ง :) - person kilokahn; 01.10.2017
comment
ถือเป็นแนวปฏิบัติที่ดีสำหรับการเชื่อมต่อแบบสากลหรือไม่? การทดสอบจะไม่ซับซ้อนและยังทำให้แย่ลงหากคุณมีธุรกรรมใช่หรือไม่ - person badc0re; 26.12.2018
comment
@ badc0re ตามที่เอกสารระบุไว้ pyMongo ใช้การรวบรวมการรวมกลุ่มในระดับไดรเวอร์ ยิ่งคุณเปิด/ปิดการเชื่อมต่อบ่อยเพียงใด แอปพลิเคชันของคุณก็จะยิ่งช้าลง และจำนวนการเชื่อมต่อที่เปิดไปยังฐานข้อมูลในช่วงเวลาใดก็ตาม - person kilokahn; 26.02.2019