活动 record-import 正在创建重复记录
active record-import is creating duplicate records
我在 class 方法中使用 active-record 导入 gem 来导入从 csv 文件读取的列表数组,如下面的代码所示:
def self.import_listings(file)
start = Time.now
count = 0
valid_listings = Array.new
CSV.foreach(file.path, headers: true, encoding:'iso-8859-1:utf-8') do |row|
data = {}
row.to_hash.each do |k, v|
key = MAP[k]
data[key] = v
end
unless data[:vin] == nil
listing = Listing.new
listing.title = "#{data[:year]} #{data[:make]} #{data[:model]}"
listing.approved = true
unless data[:all_images] == nil
listing_images = data[:all_images].split(",")
i = 0
[:image, :imagefront, :imageback, :imageleft, :imageright, :frontinterior, :rearinterior].each do |image|
unless listing_images.size < 1
data[image] = CsvUploading::picture_from_url(listing_images[i])
i += 1
end
end
end
data.delete(:all_images)
data[:approved] = true
listing.attributes = data
valid_listings << listing
end
end
begin
Listing.import valid_listings, on_duplicate_key_update: { conflict_target: [:title, :vin], columns: [user_id: :user_id, newused: :newused]}# , :stocknumber, :model, :year, :trim, :miles, :enginedescription,:cylinder,:fuel,:transmission, :price, :color, :interiorcolor, :options, :description, :image, :image, :imagefront, :imageback, :imageleft, :imageright, :frontinterior, :rearinterior]
rescue
p "some issue"
end
finish = Time.now
puts diff = finish - start
end
根据 active-record 导入文档,我正在尝试将列表的标题和 VIN 字段设置为冲突 targets.In 列表的 VIN 字段冲突的情况,我想进行更新而不是创建。
但现在,每次我 运行 CSV 上传时,它都会从 Listing.import 创建一个新列表,而不检查它是否有冲突。
我哪里错了?
您的屏幕截图显示您正在使用 SQLite,但 documentation 表示此功能仅支持 MySQL 和 PostgreSQL。您将需要使用受支持的数据库!
我的第一个回答,希望对以后的人有用:
On Duplicate Key Update 行为取决于数据库本身对这些列的唯一约束 - 因为您看到的是重复记录,所以可以安全地假设您没有这样的约束。
由于数据库未报告唯一约束冲突,因此它没有理由更新现有行! this Stack Overflow question, "How to correctly do upsert in postgres 9.5" 中的答案对此进行了更深入的解释,并显示了正在发出的查询的类型。
您应该能够通过在 VIN 和标题列上添加唯一约束或索引来解决此问题,例如 Rails 执行如下操作的迁移:
class AddUniqueIndexToListingsOnVinAndTitle < ActiveRecord::Migration
def change
add_index :listings, [:vin, :title], unique: true
end
end
一些您可能会觉得有用的信息(不确定您使用的是 PostgreSQL 还是 MySQL):
activerecord-import
source which builds these queries
- PostgreSQL UPSERT details
- MySQL UPSERT reference
我在 class 方法中使用 active-record 导入 gem 来导入从 csv 文件读取的列表数组,如下面的代码所示:
def self.import_listings(file)
start = Time.now
count = 0
valid_listings = Array.new
CSV.foreach(file.path, headers: true, encoding:'iso-8859-1:utf-8') do |row|
data = {}
row.to_hash.each do |k, v|
key = MAP[k]
data[key] = v
end
unless data[:vin] == nil
listing = Listing.new
listing.title = "#{data[:year]} #{data[:make]} #{data[:model]}"
listing.approved = true
unless data[:all_images] == nil
listing_images = data[:all_images].split(",")
i = 0
[:image, :imagefront, :imageback, :imageleft, :imageright, :frontinterior, :rearinterior].each do |image|
unless listing_images.size < 1
data[image] = CsvUploading::picture_from_url(listing_images[i])
i += 1
end
end
end
data.delete(:all_images)
data[:approved] = true
listing.attributes = data
valid_listings << listing
end
end
begin
Listing.import valid_listings, on_duplicate_key_update: { conflict_target: [:title, :vin], columns: [user_id: :user_id, newused: :newused]}# , :stocknumber, :model, :year, :trim, :miles, :enginedescription,:cylinder,:fuel,:transmission, :price, :color, :interiorcolor, :options, :description, :image, :image, :imagefront, :imageback, :imageleft, :imageright, :frontinterior, :rearinterior]
rescue
p "some issue"
end
finish = Time.now
puts diff = finish - start
end
根据 active-record 导入文档,我正在尝试将列表的标题和 VIN 字段设置为冲突 targets.In 列表的 VIN 字段冲突的情况,我想进行更新而不是创建。
但现在,每次我 运行 CSV 上传时,它都会从 Listing.import 创建一个新列表,而不检查它是否有冲突。
我哪里错了?
您的屏幕截图显示您正在使用 SQLite,但 documentation 表示此功能仅支持 MySQL 和 PostgreSQL。您将需要使用受支持的数据库!
我的第一个回答,希望对以后的人有用:
On Duplicate Key Update 行为取决于数据库本身对这些列的唯一约束 - 因为您看到的是重复记录,所以可以安全地假设您没有这样的约束。
由于数据库未报告唯一约束冲突,因此它没有理由更新现有行! this Stack Overflow question, "How to correctly do upsert in postgres 9.5" 中的答案对此进行了更深入的解释,并显示了正在发出的查询的类型。
您应该能够通过在 VIN 和标题列上添加唯一约束或索引来解决此问题,例如 Rails 执行如下操作的迁移:
class AddUniqueIndexToListingsOnVinAndTitle < ActiveRecord::Migration
def change
add_index :listings, [:vin, :title], unique: true
end
end
一些您可能会觉得有用的信息(不确定您使用的是 PostgreSQL 还是 MySQL):
activerecord-import
source which builds these queries- PostgreSQL UPSERT details
- MySQL UPSERT reference