2017-08-23 1 views
0

Ich benutze die Riot API für League of Legends, um in Python zieht. Ich habe eine Sammlung, die nur IDs für Matchmade-Spiele ist, die ich nicht aus der API gezogen habe und eine andere, die gezogene Matchmade-Spiele ist. Insgesamt habe ich derzeit 94.040 gezogene Matches und 224.346 Match-IDs, die ich noch nicht gezogen habe.Wie beschleunigt man diese PyMongo Abfrage/Schleife

In meinem Code überprüfe ich Profile von Personen nach neuen Übereinstimmungs-IDs, um sie gegen die Übereinstimmungen hinzuzufügen, die ich bereits habe, bevor ich sie zu der Sammlung von IDs hinzufüge, die ich noch nicht gezogen habe. Es dauert etwa 7 Sekunden für jede Iteration durch die zweite Sammlung.find, und ich bin mir nicht sicher warum. Ich habe beide Sammlungen indiziert, und wenn ich collection.find ({}) .sort ({}) benutzte, dauerte es aus irgendeinem Grund länger.

Hier ist mein Code:

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

So wurden Sie die Datenbank jeder zurückkehren zu müssen:

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

Ich möchte nur sicherstellen, dass ich Ihre innere Schleife richtig verstehe. Ziehen Sie jeden Eintrag in der Übereinstimmungssammlung aus und vergleichen Sie ihn mit der aktuellen Übereinstimmungs-ID, um festzustellen, ob er bereits in der Datenbank vorhanden ist? –

+0

Ja. Ich kann ein Beispiel dafür geben, wie der JSON aussieht, wenn das helfen würde, aber ich überprüfe jede Übereinstimmungs-ID nach allen Übereinstimmungs-IDs, die ich bereits in der Datenbank habe, bevor ich sie der Sammlung von Übereinstimmungen hinzufüge, die sein müssen gezogen. – malsatori

+0

Anstatt durch alle zu iterieren, könnten Sie eine Abfrage wie 'if matchs.find ('game_id': 'match_id') machen. Count() == 0' _ // Das Match existiert nicht in der Datenbank_. Außerdem entschuldige ich mich im Voraus, wenn die .count() für Pymongo nicht so funktioniert. Ich habe es mit Mongo in anderen Sprachen benutzt, aber das nicht. Ich werde nachsehen und zum Bearbeiten zurückkehren. –

Antwort

0

Statt durch alle von ihnen einer nach dem anderen von Iterieren Sie eine Abfrage wie zu tun einzelnes Dokument in der Übereinstimmungssammlung, die ich denke, ist die Datenbank, die ~ 95.000 Einträge hat (korrigieren Sie mich, wenn ich falsch liege), und dann durchlaufen jede von ihnen, um zu überprüfen, ob die ID bereits existierte. Also das heißt:

  1. ~ 95.000 Iterationen durch die Datenbank
  2. ~ 95.000 Iterationen von Ihrem Programm überprüft nach einem passenden id

So iterieren Sie ~ 190.000-mal, und das ist nicht inklusive Der gesamte Overhead Ihres Programms, der die Datenbankergebnisse speichert und abruft, damit Sie durch iterieren können.

Mithilfe von matches.find().count() können Sie die Datenbankindizes jedoch für Sie verwenden. Anstatt alle 95.000 Dokumente nacheinander zu durchlaufen, kann die Datenbank ihre Indizes verwenden, um zu sehen, ob das, was Sie suchen, viel schneller existiert. Darüber hinaus müssen Sie die zusätzlichen 95.000 Mal nicht wiederholen, sobald die Datenbank den Wert .count() zurückgibt, da Sie nur eine if-Anweisung benötigen, um zu sehen, ob dieser Wert 0 oder 1 ist. Das spart Iterationen und reduziert den Overhead Ihres Programms erheblich und beschleunigt so die Ausführung.

Ich bin mir nicht sicher, ob ich das klar genug gemacht habe, also stellen Sie bitte Fragen in den Kommentaren, um sicherzustellen, dass Sie genau verstehen, was vor sich geht.

+1

Danke für die Erklärung! Das macht Sinn. Meine einzige andere Frage wäre, wenn ich die matches.find ({'game_id': match_id}) verwende, und die 'game_id' ist ein Index, macht das schneller und ist nicht so schnell wie die .count() Funktion? – malsatori

+0

Also die .count() huckelt nur von 'Übereinstimmungen.find ({'game_id': match_id}) ', es zeigt an, wie viele Dokumente gefunden werden. Wenn Sie möchten, können Sie einfach überprüfen, ob 'matchs.find ({'game_id': match_id})' 'ein nicht leeres Array zurückgibt oder mit Daten gefüllt ist. Der eigentliche Schlüssel ist, dass wir gezielt in der Datenbank suchen, anstatt 'matches.find ({})' zu verwenden und alle Ergebnisse zu erhalten. Außerdem, nur weil ich neugierig bin, wie viel war die Geschwindigkeit? –

+0

Bevor ich begann, den Code laufen zu lassen, hatte ich ~ 130.000 Einträge und es dauerte etwa 7 Sekunden jedes Mal, wenn es gedruckt wurde. Nachdem ich es aktualisiert habe, um .count() zu verwenden, dauert es etwa 1 Sekunde oder eine Zehntelsekunde pro Iteration. Viel schneller! Bis zu etwa 485.000 Einträge jetzt. – malsatori