2017-10-01 14 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 

次のように私のデータベースのコードは次のとおりです。

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 
あなた "をsetAttributes()" では

答えて

2

、名前で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 "プロセスごとにこのクライアントを1回作成し、すべての操作で再利用します。リクエストごとに新しいクライアントを作成するのはよくある間違いですが、非常に非効率です。

私は、あなたが、あなたの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

関連する問題