2017-08-23 8 views
0

私はPythonでプルを作るために、League of LegendsのRiot APIを使用しています。私はAPIから引っ張っていないマッチメイドゲームのIDと引っ張ったマッチメイドゲームのIDだけのコレクションを持っています。私は現在、94,040の試合と224,346試合のIDを持っています。このPyMongoクエリ/ループをスピードアップするには

私のコードでは、私がまだ引っ張っていないIDのコレクションに追加する前に、私がすでに持っているマッチに対して追加する新しいマッチIDのプロフィールをチェックしています。それは2回目のcollection.findを通してそれぞれの反復のために約7秒を要しています、そして、なぜ私は確信していません。私はコレクションのインデックスを両方とも持っていて、collection.find({})sort({})を使用していたときに何らかの理由で実際に時間がかかりました。ここで

は私のコードです:

import pymongo 
import time 


client = pymongo.MongoClient('mongodb://localhost') 
match_db = client.matched_games 
summoner_db = client.summoner_match_history 
match_id_db = client.match_id 

matches = match_db.matches 
summoners = summoner_db.summoners 
match_id = match_id_db.match 


def main(): 
    for matchid in summoners.find({}, {'matches.gameId': 1, '_id': 0}, no_cursor_timeout=True): 
     timer = time.time() 
     try: 
      for match in matchid['matches']: 
       print(match) 
       match = match['gameId'] 
       for k in matches.find({}): 
        k = k['gameId'] 
        if k == match: 
         print(time.time() - timer) 
         timer = time.time() 
         print('Already have match #' + str(k)) 
         break 
       else: 
        print(time.time() - timer) 
        timer = time.time() 
        print('Inserting match #' + str(match) + '.') 
        match_id.insert({'match_id': match}) 
     except KeyError as e: 
      print(e) 
      pass 
     except pymongo.errors.DuplicateKeyError as e: 
      # print(e) 
      pass 

if __name__ == '__main__': 
    main() 
+0

私はちょうどあなたの内部ループを正しく理解していることを確認したいです。一致コレクションのすべてのエントリを取り出し、それが現在の一致IDと比較して、データベースに既に存在するかどうかを確認していますか? –

+0

はい。 JSONがどのように見えるかの例を投稿できますが、必要な一致のコレクションに追加する前に、データベース内にあるすべての一致IDで各一致IDを確認しています引っ張られた。 – malsatori

+0

これらのすべてを反復するのではなく、 'matches_find( 'game_id': 'match_id')のようなクエリを実行できますか?count()== 0' _ // match_はデータベースに存在しません。また、pymongoの.count()がこのように動作しない場合は、事前に謝罪します。私は他の言語でMongoと一緒に使用しましたが、これは使用しませんでした。私はそれを見て編集に戻る。 –

答えて

0

代わりにそれらのすべてを一度に1を反復の、あなたのようなクエリを行うことができます。だから、あなたはすべてのデータベース・リターンを持った

if matches.find('game_id': 'match_id').count() == 0 //Match does not exist in the database.

私が間違っていれば私を訂正して〜95,000のエントリを持っているデータベースだと思っています。そして、IDがすでに存在しているかどうかをチェックするためにそれぞれを繰り返します。だから意味:データベースによって

  1. 〜95,000回の反復
  2. 〜95,000あなたは〜19万回反復されている一致するidので

をチェックしてプログラムすることにより、反復、およびそれを含めていませんプログラムのオーバーヘッドのすべてが、反復処理のためにデータベース結果を格納しフェッチします。

ただし、matches.find().count()を使用すると、データベースインデックスを使用することになります。 95,000のすべての文書を順番に反復する代わりに、データベースは索引を使用して、探しているものがはるかに高速に存在するかどうかを確認できます。さらに、データベースが.count()の値を返すと、追加の95,000回の反復処理を行う必要はありません。if文が必要なのは、その値が0または1であることだけです。これにより、反復回数が節約され、プログラムのオーバーヘッドが大幅に削減されます。実行をスピードアップします。

私はそれを十分に明確にしているかどうか分からないので、コメントに質問をして、何が起こっているかを十分に理解してください。

+1

説明をありがとう!これは理にかなっています。私の唯一の他の質問は、matches.find({'game_id':match_id})を使用していて、 'game_id'がインデックスである場合、それは速くなり、 () 関数? – malsatori

+0

したがって、.count()は 'マッチするだけでピギーバックします。find({'game_id':match_id}) '、find()が見つかったドキュメントの数を示します。あなたが望むのであれば、 'matches.find({'game_id':match_id})'が空でない配列を返すか、あるいは何らかのデータが入力されているかどうかだけを調べることができます。真の鍵は、 'matches.find({}) 'を使用せず、すべての結果を取得するのではなく、データベース内でターゲットを絞った検索を行うことです。また、私が好奇心を持っているからといって、スピードはどれくらいですか? –

+0

コード実行を開始する前に、130,000件のエントリがあり、印刷するたびに約7秒かかっていました。 .count()を使用するように更新した後は、反復ごとに0.1秒か10秒かかります。もっと早く!最大約485,000件のエントリー。 – malsatori

関連する問題