3

I am using active-record import gem in a class method to import array of listings read from csv file as shown in code below:

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

As per active-record import documentation, i am trying to set a watcher on the title and VIN fields of listing as conflictied targets.In case of conflict of VIN field of a listing, I want to do an update instead of create.

But right now, it's creating a new listing from Listing.import every time I am running a CSV upload and not checking if its conflicted.

Where am I going wrong?

enter image description here

1 Answer 1

3
+50

Your screenshot shows that you are using SQLite, but the documentation says that this feature is only supported for MySQL and PostgreSQL. You will need to use a supported database!


My first answer, in case it's useful to someone in the future:

The On Duplicate Key Update behaviour depends on there being a unique constraint on those columns in the database itself – because you're seeing duplicate records, it's safe to assume that you don't have such a constraint.

As the database isn't reporting a conflict on a unique constraint, there's no reason it would update an existing row! The answer in this Stack Overflow question, "How to correctly do upsert in postgres 9.5" explains this in a bit more depth and shows the kind of query that is being issued.

You should be able to solve this by adding a unique constraint or index on the VIN and title columns, for example a Rails migration that does something like this:

class AddUniqueIndexToListingsOnVinAndTitle < ActiveRecord::Migration
  def change
    add_index :listings, [:vin, :title], unique: true
  end
end

Some more info you might find useful (not sure whether you're using PostgreSQL or MySQL):

Sign up to request clarification or add additional context in comments.

9 Comments

This is what I was thinking too (I was doing some research on this question as you posted your answer). In my test, the import throws a PG::InvalidColumnReference: ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification when you don't have a unique index on the conflict target column. I wasn't able to reproduce the duplicate records because of this.
Good catch @DerekHopper! It would be good to know more about the setup (I wonder if it's a database that doesn't support upserting?) @SauravPrakash what database are you using, and are there any constraints or indexes on the listings table?
@jpn : Adding a unique index does help but now I am getting a 'ConstraintException: UNIQUE constraint failed' error for duplicate records. Which indicates it does check that it's a duplicate one but on_duplicate_key_update still doesn't work and won't update the data.
@SauravPrakash if the migration to create the unique constraint is failing, its probably because there is duplicate data in the database which is violating the unique constraint. I think you'll need to clean up the database before you can create the unique constraint.
@John I took care of the migration error. This error is arising when I am using the import function while uploading a csv twice. First time, its all dandy. Second time I get the error. What should happen is it should update the changes to the records found but it isn't.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.