2016-06-01 2 views
2

eine Reihe von Modell-IDs Gegeben:Wie filtert man die Werte einer Modellspalte, die nicht in der Datenbank existieren?

ids = [1, 2, 3] 

Wie kann ich ein Array der IDs erhalten, die nicht bereits in der Datenbank vorhanden ist? Ich kann tun:

ids.reject { |id| Model.exists?(id: id) } 

aber ich möchte nicht eine separate Datenbankabfrage für jede ID machen. Wie erhalten Sie die nicht vorhandenen IDs in einer einzigen Datenbankabfrage?

+2

Nicht sicher über die RoR-Syntax, aber die SQL-Art, es zu tun ist; Erstellen Sie einen Datensatz mit [1,2,3] und identifizieren Sie dann, welche nicht in der Zieltabelle vorhanden sind ... 'SELECT sample. * FROM (AUSWAHL 1 AS id UNION ALLE AUSWAHL 2 AS id UNION ALLE AUSWAHL 3 AS id) Beispiel LINKER JOIN Ziel ON target.id = Beispiel.ID WHERE Ziel.ID IS NULL' – MatBailie

+0

@MatBailie +1 für die Bereitstellung einer reinen SQL-Lösung –

Antwort

6

können Sie wie unten verwenden, wenn Sie Schienen 4 oder höher

ids = [1, 2, 3] 
existing_ids = Model.where(id: ids).ids 
ids - existing_ids 

verwenden Wenn Sie Schienen 3 verwenden, müssen Sie

ids = [1, 2, 3] 
existing_ids = Model.where(id: ids).pluck(:id) 
ids - existing_ids 

Lesen Sie mehr über pluck und idshere und here beziehungsweise.

Vielen Dank Stefan für mich über ids Methode zu zeigen.

+0

Sie können '.ids' anstelle von' .pluck (: id) 'verwenden – Stefan

+0

Danke @Stefan. Das war etwas Neues für mich. Ich aktualisiere die Antwort. – Sebin

3

TL; DR: Wenn ids ist das Array von IDs, die Sie überprüfen möchten und MyModel ist der Name des Modells dann die folgende ist ein Array der IDs, die nicht existieren: ids - MyModel.where(id: ids).pluck(:id)


MyModel.where(id: ids) gibt alle Datensätze für MyModel zurück, deren ID mit einem der Werte Ihres ids Arrays übereinstimmt. Aber wenn Sie .pluck(:id) hinzufügen, wird ein Array mit nur den IDs für diese Datensätze zurückgegeben. So ist MyModel.where(id: ids).pluck(:id) das Array von Datensatz-IDs, die Ihren ids Array-Werten entsprechen.

Dann können Sie den Minus-Operator verwenden, um die beiden Arrays zu unterscheiden. array1 - array2 gibt nur die Elemente von Array1 zurück, die nicht in Array2 enthalten sind.

Also alles zusammen setzen Sie erhalten ids - MyModel.where(id: ids).pluck(:id).

+0

Vielen Dank für Ihre Antwort. Zwei Dinge: du brauchst nicht das 'all' für' pluck', du kannst MyModel.pluck (: id) direkt machen und Sebins Antwort ist ein bisschen effizienter, da es möglicherweise ein kleineres Array instanziiert (habe keine markierte es aber). –

+1

@AlexPopov Es scheint, dass Sie meine Änderungen nicht gesehen haben, aber ich hatte bereits meine Antwort bearbeitet, um sie effizienter zu machen, genau wie Sie es tatsächlich gesagt haben;) – Pholochtairze

Verwandte Themen