MehdiZonjy / json-transqlify

Transforms and loads JSON to a MySQL db
https://mzmuse.com/blog/introducing-json-transqlify
6 stars 0 forks source link

batch Update #2

Closed nyousefzai closed 6 years ago

nyousefzai commented 6 years ago

Hi, I have a hard time '' updating records '' like your first example I have an array of objects I am able to insert it and when I do batch-upsert it gets created again.

if you can explain a little more in update area that will help. an example will be nice. Thanks for sharing your lovely work. nice job.

MehdiZonjy commented 6 years ago

Thanks for giving Json-transqlify a shot.

I'll try my best to give a general example but I might be able to help you better if you could share with me the structure of your Json, table schema and your current transqlify definition file.

Assuming you have an array of user records that look something like

{
  "id": "<uuid>",
  "firstName": "<string>",
  "lastName": "<string>",
  "age": "<number>"
}

and maybe the table schema is something like

CREATE TABLE `users` (
  `id` char(36) NOT NULL,
  `age` int(11) NOT NULL,
  `name` varchar(128) NOT NULL,
   PRIMARY KEY (`id`)
)

The following yaml definition file utilizes Batch-Upsert loader and allows you to insert user JSON into the corresponding users table and overwrite any existing records that hold the same Id

Insert

version: 1.0
loaders:
  - batchUpsert:
      label: InsertUser
      source: $entity
      tableName: users
      transform:
        columns:
          - column: id
            value: $entity.id
          - column: name
            value: $entity.fistName + $entity.lastName
          - column: age
            value: $entity.age

all is left is to build a jsonTransqlifier based on the definition you just created

const createFactory = require('json-transqlify').createFactory;

const db = {
  host: 'localhost',
  user: 'root',
  password: '',
  database: 'json_transqlify_demos',
  connectionLimit: 2
}

const factory = createFactory(db)
const transqlifier = factory.createTransqlifier('./upsert-users.yaml'); // the definition file from above

const main = async () => {
  const users =[
     { id: '11d7781b-3f58-4080-9a78-063c14e2e71f', firstName: 'Dextar', lastName: 'Morgan', age: 35 },
     { id: '213e287e-d2c7-4014-aa11-699d98afabd1', firstName: 'Debra', lastName: 'Morgan', age: 30 },
     { id: '0cc26d2d-6dcd-4663-8d9d-d27fbe9825e1', firstName: 'James', lastName: 'Doakes', age: 39 }
  ]
  await transqlifier(users)
  factory.closePool()
}

main()

just for the fun of it, let's insert this user manually to the db before running the script and see it get updated

INSERT INTO users (id, name, age) VALUES ( '11d7781b-3f58-4080-9a78-063c14e2e71f' , 'Harry Morgan', 59)

when running the script, two new records will be inserted, and the existing one will get updated and the name will change from Harry Morgan to Dextar Morgan along with the age as well.

Please note there are currently a variety of loaders. The one i used here is batch-upsert-loader The generated SQL command is something along the lines of

INSERT INTO users (id,name,age) VALUES (?,?,?),(?,?,?),(?,?,?)
    ON DUPLICATE KEY UPDATE id = VALUES(id),name = VALUES(name),age = VALUES(age)

Let me know if this helps.

nyousefzai commented 6 years ago

Thanks, it totally works in your example however I could not make it work with my schema. in my json file I have a lot of fields . I have mapper which I can make the json smaller, but prefer to not use it.
i want to be able to insert and update, the update is more important for me.

thanks for your help. { "sysid": "148843862", "AddressBoxNumber": "", "AddressCarrierRoute": "", "City": "San Marcos", "AddressCountry": "", "CountyOrParish": "Hays", "PostalCode": "78666", "obsolete_StateOrProvince": "TX", "AddressStreetAdditionalInfo": "", "UnparsedAddress": " test", "AddressStreetDirPrefix": "", "AddressStreetDirSuffix": "", "StreetName": " Barn", "StreetNumber": "18", "StreetSuffix": "", "UnitNumber": "", "NativeAppliances": "Oven,Water Heater,Dishwasher,Washer", "AssociationFee": "360", "AssociationFee2": "", "AssociationFeePeriod": "Annually", "Baths1Qtr": "", "Baths3Qtr": "", "BathroomsFull": "2", "BathroomsHalf": "0", "BedroomsTotal": "3", "NativeBoard": "", "CancelationDate": "", "BuyerAgencyCompensation": "Buy Agnt 3.000, Sub Agnt 0.000", "NativeCommunityFeatures": "", "ConstructionMaterial": "All Sides Masonry,Brick Veneer,HardiPlank Type,Stone Veneer", "ContingentDate": "", "NativeCooling": "Central Air", "CoolingPresent": "Yes", "Directions": "Exit 210 Yarrington Road. West on Yarrington Road into neighborhood. Left on Old Settlers. Left on Hay Barn.", "Disclaimer": "", "FireplacesTotal": "0", "FireplacesIndicator": "No", "Floors": "Concrete", "Foundation": "Slab", "GarageSpaces": "", "NativeHeating": "Central Heat", "HorseFacilities": "", "obsolete_HorseYN": "", "HotTub": "", "HotTubIndicator": "", "VirtualTourURLUnbranded": "", "Inclusions": "", "ListingAreaCode": "HH", "ListingAreaDescription": "HH", "ListingID": "2913210", "MlsStatus": "Withdrawn", "ListingStatusCode": "", "ListPrice": "156973", "ListPricePrevious": "", "LivingArea": "1252", "LotSizeAcres": "0.112", "LotSizeAreaSqFeet": "", "LotSizeDimensions": "", "MapCoordinate": "", "ModificationTimeStamp": "2013-01-22T07:53:20", "OriginalListPrice": "156973", "ParkingCarPort": "", "ParkingCoveredParking": "", "ParkingTotal": "", "PendingDate": "", "PhotosChangeTimestamp": "2013-01-21T09:32:49", "PoolPresent": "", "PorchType": "", "PropertySubTypeDescription": "House", "TaxAnnualAmount": "3765", "PropertyTypeDescription": "Residential", "PropertyTypeID": "4", "PropertyTypeStandardName": "Single Family", "PublicRemarks": "", "REO": "", "NativeRoof": "Composition Shingle", "RoomsBasementArea": "", "RoomsBasementDim": "", "RoomsDenDescription": "", "RoomsDenDim": "", "RoomsDiningRoomDim": "", "RoomsDiningRoomPresent": "Y", "RoomsFamilyDescription": "", "RoomsFamilyRoomDim": "", "RoomsFamilyRoomPresent": "", "RoomsKitchenDimensions": "", "RoomsLaundryDimensions": "", "RoomsLivingRoomDim": "", "RoomsLivingRoomPresent": "", "RoomsOfficeDescription": "", "RoomsOfficeDimensions": "", "RoomsTotal": "", "ElementarySchool": "", "HighSchool": "Lehman", "SchoolJrHigh": "N/A", "MiddleOrJuniorSchool": "Laura B Wallace", "SchoolSchoolDistrict": "Hays ISD", "NativeSecurityFeatures": "", "StatusChangeTimestamp": "2013-01-22T00:00:00", "SubdivisionName": "Blanco Vista Ph 01 A", "Terms": "Conventional,FHA,VA", "NumberOfUnitsTotal": "", "Tract": "", "NativeUtilities": "Electricity on Property,Natural Gas on Property", "UtilitiesSewer": "City at Street", "UtilitiesWater": "City", "ViewIndicator": "No", "WaterfrontYN": "", "Zoning": "", "DisabilityFeatures": "", "NativeExteriorFeatures": "Curbs,Sidewalk", "FirePlaceDetails": "", "NativeInteriorFeatures": "Ceiling-High,Lighting Recessed,Walk-In Closet", "LotDesc": "", "ViewDescription": "No View", "TaxBlock": "", "TaxLot": "", "UnitFIVE_RentPerMonth": "", "UnitFOUR_RentPerMonth": "", "UnitONE_RentPerMonth": "", "UnitTHREE_RentPerMonth": "", "UnitTWO_RentPerMonth": "", "TWP": "", "UnitFIVE_Baths": "", "UnitFIVE_Beds": "", "UnitFIVE_Desc": "", "UnitFIVE_Furnished": "", "UnitFOUR_Baths": "", "UnitFOUR_Beds": "", "UnitFOUR_Desc": "", "UnitFOUR_Furnished": "", "UnitONE_Baths": "", "UnitONE_Beds": "", "UnitONE_Desc": "", "UnitONE_Furnished": "", "UnitTHREE_Baths": "", "UnitTHREE_Beds": "", "UnitTHREE_Desc": "", "UnitTHREE_Furnished": "", "UnitTWO_Baths": "", "UnitTWO_Beds": "", "UnitTWO_Desc": "", "UnitTWO_Furnished": "", "NativeAssociationAmenities": "", "NativeAssociationFeeIncludes": "Common Area Maintenance,Common Insurance", "AssociationFeePeriod2": "", "AssociationName": "", "NativeAssociationYN": "Yes", "AttachedYN": "", "BoardSubBoard": "", "BuilderModel": "", "BuilderName": "Pacesetter Homes", "NativeBuildingAreaSource": "Builder", "CarportYN": "", "Contingency": "", "NativeCropsIncludedYN": "", "CrossStreet": "", "NativeDirectionFaces": "", "NativeDisclosures": "", "NativeFencing": "Wood", "GarageAttachedYN": "", "NativeGarageYN": "Yes", "GreenBuildingCertification": "", "NativeGreenEnergyEfficient": "", "obsolete_HeatingYN": "Yes", "InternetAutomatedValuationDisplayYN": "Yes", "IDXConsumerCommentYN": "Yes", "NativeIrrigationSource": "", "NativeIrrigationWaterRightsYN": "", "NativeLeaseConsideredYN": "", "NativeLotSizeSource": "", "NativeNewConstructionYN": "", "NumberOfBuildings": "", "NativeOpenParkingYN": "", "OtherParking": "", "NativeParkingFeatures": "", "ParkName": "", "NativeRentControlYN": "", "NativeRentIncludes": "", "RoomsBathroomOneDim": "", "RoomsBathroomOneLevel": "", "RoomsBathroomThreeDim": "", "RoomsBathroomThreeLevel": "", "RoomsBathroomTwoDim": "", "RoomsBathroomTwoLevel": "", "RoomsBedroomFiveArea": "", "RoomsBedroomFiveDescription": "", "RoomsBedroomFiveDim": "", "RoomsBedroomFiveLevel": "", "RoomsBedroomFourArea": "", "RoomsBedroomFourDescription": "", "RoomsBedroomOneArea": "", "RoomsBedroomOneDescription": "", "RoomsBedroomOneDim": "", "RoomsBedroomOneLevel": "", "RoomsBedroomThreeArea": "", "RoomsBedroomThreeDescription": "", "RoomsBedroomThreeDim": "", "RoomsBedroomThreeLevel": "", "RoomsBedroomTwoArea": "", "RoomsBedroomTwoDim": "", "RoomsBedroomTwoLevel": "", "RoomsBonusRoomLevel": "", "RoomsDenArea": "", "RoomsDenLevel": "", "RoomsDiningRoomArea": "", "RoomsDiningRoomFeatures": "", "RoomsFamilyRoomArea": "", "RoomsFamilyRoomFeatures": "", "RoomsGreatRoomArea": "", "RoomsGreatRoomDescription": "", "RoomsGreatRoomDim": "", "RoomsGreatRoomLevel": "", "RoomsKitchenArea": "", "RoomsKitchenFeatures": "", "RoomsKitchenLevel": "", "RoomsLaundryArea": "", "RoomsLaundryFeatures": "", "RoomsLaundryLevel": "", "RoomsLivingRoomArea": "", "RoomsLivingRoomFeatures": "", "RoomsMasterBathroomArea": "", "RoomsMasterBathroomDescription": "Full Bath", "RoomsMasterBathroomDim": "", "RoomsMasterBathroomFeatures": "", "RoomsMasterBathroomLevel": "", "RoomsMasterBedroomArea": "", "RoomsMasterBedroomDescription": "", "RoomsMasterBedroomDim": "", "RoomsMasterBedroomFeatures": "", "RoomsMasterBedroomLevel": "", "RoomsMediaLevel": "", "RoomsOfficeArea": "", "RoomsOfficeLevel": "", "ElementarySchoolDistrict": "Blanco Vista Elem", "HighSchoolDistrict": "", "MiddleOrJuniorSchoolDistrict": "", "TaxAssessedValue": "", "TaxBookNumber": "", "TaxMapNumber": "", "UnitFIVE_UnitsTotal": "", "UnitFOUR_UnitsTotal": "", "UnitONE_UnitsTotal": "", "UnitTHREE_UnitsTotal": "", "UnitTWO_UnitsTotal": "", "WaterBodyName": "", "PostalCodePlus4": "", "StandardStatus": "Withdrawn", "PropertyType": "Residential" }

also, this is my table schema : CREATE TABLE IF NOT EXISTS listing ( id int(11) NOT NULL AUTO_INCREMENT, user_id int(11) NOT NULL DEFAULT'1', retype varchar(25) NOT NULL DEFAULT 'Residential', subtype varchar(25) NOT NULL DEFAULT 'House', price int(10) unsigned NOT NULL DEFAULT '0', originalprice int(10) unsigned NOT NULL DEFAULT '0', city varchar(100) NOT NULL DEFAULT '', state varchar(500) NOT NULL, country varchar(500) NOT NULL, description text NOT NULL, bedrooms varchar(255) NOT NULL, halfbaths varchar(255) NOT NULL, bathrooms varchar(255) NOT NULL, mls_office_id varchar(255) NOT NULL, relistingby varchar(255) NOT NULL DEFAULT 'reagent', builtin varchar(255) NOT NULL, resize int(11) NOT NULL, lotsize int(11) NOT NULL, contact_name varchar(255) NOT NULL DEFAULT 'test, contact_phone varchar(255) NOT NULL DEFAULT 'test', contact_email varchar(255) NOT NULL DEFAULT 'navid', contact_website varchar(1000) NOT NULL, contact_address text NOT NULL, show_image varchar(1000) NOT NULL, pictures mediumtext, ip varchar(75) NOT NULL DEFAULT '', dttm datetime NOT NULL DEFAULT '0000-00-00 00:00:00', dttm_modified datetime NOT NULL, purchase_contract_date date NOT NULL, status_change_date date NOT NULL, address varchar(100) NOT NULL DEFAULT '', apt varchar(75) NOT NULL DEFAULT '', postal varchar(25) NOT NULL DEFAULT '', classification varchar(25) NOT NULL DEFAULT 'Active', status varchar(25) NOT NULL, headline varchar(100) NOT NULL DEFAULT '', cats varchar(5) NOT NULL DEFAULT '', dogs varchar(5) NOT NULL DEFAULT '', smoking varchar(5) NOT NULL DEFAULT '', useremail varchar(125) NOT NULL, permanent tinyint(4) NOT NULL DEFAULT '0', latitude double NOT NULL, longitude double NOT NULL, listing_type smallint(6) NOT NULL DEFAULT '1', listing_expire varchar(255) NOT NULL DEFAULT 'normal', flag smallint(6) NOT NULL, featured_till datetime NOT NULL, mlslisting_id varchar(25) NOT NULL, rooms_total varchar(25) NOT NULL, stories varchar(25) NULL, laundry varchar(25) NULL, pool varchar(25) NOT NULL, sewer varchar(25) NOT NULL, has_hoa varchar(25) NOT NULL, hoa_fee_frequency varchar(25) NULL, hoa_fee varchar(25) NULL, listing_agent_id varchar(25) NULL, listing_agent_firstname varchar(100) NOT NULL, listing_agent_lastname varchar(100) NOT NULL, listing_office_name varchar(100) NOT NULL, PRIMARY KEY (id) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=598765;

MehdiZonjy commented 6 years ago

The reason why you aren't able to update existing records isn't because because you are missing id field from your JSON. without the id field, there won't be any conflict when inserting the record, therefore a new one will always be created.

for those records you wish to update, make sure they have an id field

nyousefzai commented 6 years ago

thanks