2016-06-01 17 views
2

鑑於模型一組ID:如何篩選數據庫中不存在的模型列的值?

ids = [1, 2, 3] 

我怎樣才能獲得的ID,這已經不存在於數據庫中的數組?我可以這樣做:

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

但我不想爲每個ID做一個單獨的數據庫查詢。在單個數據庫查詢中獲取不存在的ID的方法是什麼?

+2

不確定RoR語法,但SQL方法是這樣做的;創建一個包含[1,2,3]的數據集,然後確定目標表中不存在的數據集...'SELECT sample。* FROM(SELECT 1 AS id UNION ALL SELECT 2 AS id UNION ALL SELECT 3 AS id)示例LEFT JOIN target on target.id = sample.id WHERE target.id IS NULL' – MatBailie

+0

@MatBailie +1提供純SQL解決方案 –

回答

6

您可以使用一樣,如果你使用的是軌道4或以上

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

如下如果使用的是軌道3,你需要

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

瞭解更多關於pluckidsherehere分別。

謝謝Stefan爲我指點關於ids的方法。

+0

您可以使用'.ids'而不是'.pluck(:id)' – Stefan

+0

謝謝@Stefan。這對我來說是新事物。我正在更新答案。 – Sebin

3

TL; DR:如果ids是要檢查身份證的陣列和爲MyModel是模型的名稱,然後下面是一組ID不存在:ids - MyModel.where(id: ids).pluck(:id)


MyModel.where(id: ids)將返回MyModel的所有記錄,其ID與您的ids陣列的某個值相匹配。但是,如果添加.pluck(:id)將返回僅包含這些記錄的ID的數組。因此MyModel.where(id: ids).pluck(:id)是與您的ids數組值相匹配的記錄ID數組。

然後,您可以使用minus運算符來製作兩個數組的差異。 array1 - array2僅返回array1中不在array2中的元素。

因此,把所有東西放在一起,你會得到ids - MyModel.where(id: ids).pluck(:id)

+0

謝謝你的回答。有兩件事:你不需要用'pluck'作爲'all',你可以直接執行MyModel.pluck(:id),Sebin的回答更有效率,因爲它可能會實例化一個更小的數組標記它雖然)。 –

+1

@AlexPopov看起來你沒有看到我的編輯,但我已經編輯了我的答案,使它更加高效,就像事實上一樣;) – Pholochtairze