2017-10-01 10 views
1

MongoDB Atlas의 데이터베이스에서 읽고 쓰려고하는데 컬렉션에서 데이터를 읽을 수는 있지만 컬렉션에 쓰려고하면 PyMongo가 예외 'name은 (는) str의 인스턴스 여야합니다.'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 

내 데이터베이스 코드입니다 (I 나를 더 잘 이해하는 데 도움 코멘트 톤, 그래서 간결의 부족을 용서하시기 바랍니다있어) :

당신에
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 

답변

2

"setattributes는()", 당신은 이름으로 pymongo 컬렉션 인스턴스에 액세스 : 다음

collection = db.database[self.tablename] 

에서 "insertdata()가"다시 같은 일을 시도,하지만 지금은 "컬렉션"문자열이 아닌, 그것은 컬렉션 인스턴스의 :

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

대신, 간단하게 수행

post_id = collection.insert_one(post).inserted_id 

에 의해 MongoClient를 만들고 조작 할 때마다 코드를 작성해야한다는 것을 알았습니다. 이것은 불필요하게 복잡하고 각 작업에 대해 새로운 연결을 요구함으로써 애플리케이션 속도를 크게 떨어 뜨립니다. As the FAQ says "각 프로세스에 대해이 클라이언트를 한 번 만들고 모든 작업에 다시 사용하십시오. 각 요청에 대해 새 클라이언트를 만드는 것은 일반적인 실수입니다. 매우 비효율적입니다."

나는 당신이 당신의 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) 

이 코드는 간단하고 훨씬 빠르게 실행됩니다.

+1

고맙습니다. 귀하의 제안으로 인해 효과가있었습니다. 또한 데이터베이스 클래스를 이동하고 메인 스레드 자체에서 연결을 구현하는 것에 대한 조언을 듣고 있습니다.이 클래스는 연결 풀링과 함께 MariaDB를 사용하는 이전 버전의 응용 프로그램에서 남은 것입니다. 다시 한번 고마워요. :) – kilokahn