Knex: рдЕрдкрд░рд░реНрдЯ рдкреНрд░рдХрд╛рд░ рдХреА рдХреНрд╖рдорддрд╛ рдЬреЛрдбрд╝рдирд╛

рдХреЛ рдирд┐рд░реНрдорд┐рдд 30 рдЕрдЧре░ 2013  ┬╖  54рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: knex/knex

@adamscybot рджреНрд╡рд╛рд░рд╛ tgriesser/bookshelf#55 рдореЗрдВ рд▓рд╛рдпрд╛ рдЧрдпрд╛ - рдпрд╣ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдЪреНрдЫреА рд╕реБрд╡рд┐рдзрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИред

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

@NicolajKN рдЖрдкрдХреЛ toString() рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЗрд╕рд╕реЗ рдХрдИ рдкреНрд░рдХрд╛рд░ рдХреА рд╕рдорд╕реНрдпрд╛рдПрдВ рд╣реЛ рд╕рдХрддреА рд╣реИрдВ рдФрд░ рдбреАрдмреА (рд╕рдВрднрд╛рд╡рд┐рдд рдПрд╕рдХреНрдпреВрдПрд▓ рдЗрдВрдЬреЗрдХреНрд╢рди рд╕реБрд░рдХреНрд╖рд╛ рдЫреЗрдж) рдХреЛ рдмрд╛рдЗрдВрдбрд┐рдВрдЧ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдореВрд▓реНрдпреЛрдВ рдХреЛ рдкрд╛рд░рд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

рд╡рд╣реА рдареАрдХ рд╕реЗ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдпрд╣ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реЛрдЧрд╛:

const query = knex('account').insert(accounts);
const safeQuery = knex.raw('? ON CONFLICT DO NOTHING', [query]);

рд╕рднреА 54 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рдореИрдВ рд╕рд╣рдордд рд╣реВрдВ, рдпрд╣ рдПрдХ рдЕрдЪреНрдЫреА рд╕реБрд╡рд┐рдзрд╛ рд╣реЛрдЧреА!

:+1:

:+1:

рдореИрдВ рдПрдХ рд╕реАрдПрд╕рд╡реА рд╕реЗ рдХреБрдЫ рдбреЗрдЯрд╛ рдЖрдпрд╛рдд рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рдПрдХ рдЕрдЪреНрдЫрд╛ рдореМрдХрд╛ рд╣реИ рдХрд┐ рдХреБрдЫ рд░рд┐рдХреЙрд░реНрдб рдкрд┐рдЫрд▓реЗ рдЖрдпрд╛рдд рд╕реЗ рдУрд╡рд░рд▓реИрдк рд╣реЛрддреЗ рд╣реИрдВ (рдпрд╛рдиреА рдкрд┐рдЫрд▓реА рдмрд╛рд░ 1 рдЬрдирд╡рд░реА рд╕реЗ 31 рдордИ рддрдХ рдЖрдпрд╛рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЗрд╕ рдмрд╛рд░ 31 рдордИ рд╕реЗ 18 рдЬреВрди рддрдХ рдЖрдпрд╛рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛)ред

рд╕реМрднрд╛рдЧреНрдп рд╕реЗ рддреГрддреАрдп рдкрдХреНрд╖ рдкреНрд░рдгрд╛рд▓реА рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рд░реВрдк рд╕реЗ рдЕрджреНрд╡рд┐рддреАрдп рдЖрдИрдбреА рдкреНрд░рджрд╛рди рдХрд░рддреА рд╣реИред

рдирдП рд░рд┐рдХреЙрд░реНрдб рдбрд╛рд▓рдиреЗ рдФрд░ рдкреБрд░рд╛рдиреЗ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рддрд░реАрдХрд╛ рдХреНрдпрд╛ рд╣реИ?

рдореИрдВрдиреЗ рдЕрднреА рддрдХ рдЗрд╕рдХреА рдХреЛрд╢рд┐рд╢ рдирд╣реАрдВ рдХреА рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВ рд╕реЛрдЪ рд░рд╣рд╛ рдерд╛ рдХрд┐ рдпрд╣ рдРрд╕рд╛ рдХреБрдЫ рд╣реЛрдЧрд╛:

var ids = records.map(function (json) { return json.id })
  ;

Records.forge(ids).fetchAll().then(function () {
  records.forEach(function (record) {
    // now the existing records are loaded in the collection ?
    Object.keys(record).forEach(function (key) {
      Records.forge(record.id).set(key, record[key]);
    });
  });
  Records.invokeThen('save').then(function () {
    console.log('Records have been either inserted or updated');
  });
});

рд╕рд╛рде рд╣реА, рдХрднреА-рдХрднреА рдЬреЛ рдЪреАрдЬрд╝ рдореИрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рд╡рд╣ рдПрдХ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдЖрдИрдбреА рдорд╛рди, рдЬреИрд╕реЗ рд╣реИрд╢ рджреНрд╡рд╛рд░рд╛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЙрди рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдореИрдВ рд╕рд┐рд░реНрдл рдбреЗрдЯрд╛ рдЬреЛрдбрд╝рдирд╛ рдпрд╛ рдмрджрд▓рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред

рдореИрдВ рд╣рдореЗрд╢рд╛ SQL рдХреЛ рдкрд╛рд░рдВрдкрд░рд┐рдХ SQL рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддрд╛ред рд╕реНрдкрд╖реНрдЯ рд╕рдВрдмрдВрдз рдореИрдкрд┐рдВрдЧ рдФрд░ рдЗрдВрдбреЗрдХреНрд╕ рдХреЗ рд▓рд╛рдн рдХреЗ рд╕рд╛рде рдЕрдХреНрд╕рд░ рдореИрдВ рдЗрд╕реЗ рд╣рд╛рдЗрдмреНрд░рд┐рдб рдиреЛрдПрд╕рдХреНрдпреВрдПрд▓ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВред

:+1:

рдирдорд╕реНрддреЗ,
рдЗрд╕ рдирдП рдлреАрдЪрд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреЛрдИ рдЦрдмрд░ рд╣реИ?

рдпрд╛ рдХреЛрдИ рдЙрджрд╛рд╣рд░рдг рд╕реБрдЭрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬреЛ рджрд┐рдЦрд╛рддрд╛ рд╣реИ рдХрд┐ MySQL рдХреЗ рд▓рд┐рдП рдЗрд╕ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рдЕрдиреБрдХрд░рдг рдХреИрд╕реЗ рдХрд░реЗрдВ?

рдзрдиреНрдпрд╡рд╛рдж

рдЕрднреА рдореИрдВ рдЗрд╕реЗ raw рдХреЗ рд╕рд╛рде рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдореИрдВ рдЗрд╕реЗ рдЬрд▓реНрдж рд╣реА рдпрд╣рд╛рдВ рдЙрдкрд▓рдмреНрдз рдХрд░рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдбрд╝реА рдореЗрд╣рдирдд рдХрд░ рд░рд╣рд╛ рд╣реВрдВред

рдкреЛрд╕реНрдЯрдЧреНрд░реЗрдЬ рдиреЗ рдЕрднреА-рдЕрднреА рдЕрдкреНрд╕рд░реНрдЯ рд╕рдкреЛрд░реНрдЯ рдХреЛ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рд╣реИ: +1:

http://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=168d5805e4c08bed7b95d351bf097cff7c07dd65

https://news.ycombinator.com/item?id=9509870

рд╕рд┐рдВрдЯреИрдХреНрд╕ INSERT ... ON CONFLICT DO UPDATE рд╣реИ

рдореИрдВ MySQL рдореЗрдВ REPLACE INTO рдХрд░рдиреЗ рдХрд╛ рддрд░реАрдХрд╛ рдвреВрдВрдв рд░рд╣рд╛ рдерд╛ рдФрд░ рдореБрдЭреЗ рдпрд╣ рд╕реБрд╡рд┐рдзрд╛ рдЕрдиреБрд░реЛрдз рдорд┐рд▓рд╛ред рдЪреВрдВрдХрд┐ REPLACE рдФрд░ INSERT рдореЗрдВ MySql рдореЗрдВ рдмрд┐рд▓реНрдХреБрд▓ рд╕рдорд╛рди рд╕рд┐рдВрдЯреИрдХреНрд╕ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕реЗ ON DUPLICATE KEY UPDATE рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реЛрдЧрд╛ред рдХреНрдпрд╛ REPLACE рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдХреЛрдИ рдпреЛрдЬрдирд╛ рд╣реИ? рдХреНрдпрд╛ рдкреАрдЖрд░ рдХреБрдЫ рдореВрд▓реНрдпрд╡рд╛рди рд╣реЛрдЧрд╛?

рдЗрд╕ рдкрд░ рдХреЛрдИ рдЕрдкрдбреЗрдЯ, рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ PostreSQL 9.5 рдХреЗ рд╕рд╛рде?

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдкреНрд░рд╢реНрди рдпрд╣ рд╣реИ рдХрд┐ рдкреЛрд╕реНрдЯрдЧреНрд░реЗрдПрд╕рдХреНрдпреВрдПрд▓ рдФрд░ рдорд╛рдИрдПрд╕рдХреНрдпреВрдПрд▓ рдЬреИрд╕реА рд╡рд┐рднрд┐рдиреНрди рдмреЛрд▓рд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рдорд╛рди upsert рд╡рд┐рдзрд┐ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдХрд╛ рдЦреБрд▓рд╛рд╕рд╛ рдХрд┐рдпрд╛ рдЬрд╛рдП рдпрд╛ рдирд╣реАрдВред Sequelize рдореЗрдВ, upsert рдХреЗ рд╡рд╛рдкрд╕реА рдореВрд▓реНрдп рдХреЗ рд╕рдВрдмрдВрдз рдореЗрдВ рдПрдХ рдореБрджреНрджрд╛ рдЙрдард╛рдпрд╛ рдЧрдпрд╛ рд╣реИ: https://github.com/sequelize/sequelize/issues/3354ред

рдореБрдЭреЗ рдПрд╣рд╕рд╛рд╕ рд╣реИ рдХрд┐ рдХреБрдЫ KnexJS рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╡рд┐рдзрд┐рдпреЛрдВ рдореЗрдВ рд╡рд┐рднрд┐рдиреНрди рдмреЛрд▓рд┐рдпреЛрдВ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рд╡рд╛рдкрд╕реА рдореВрд▓реНрдпреЛрдВ рдХреЗ рд╕рдВрдмрдВрдз рдореЗрдВ рднреЗрдж рд╣реИрдВ (рдЬреИрд╕реЗ insert , рдЬрд╣рд╛рдВ рдкрд╣рд▓реА рдбрд╛рд▓реА рдЧрдИ рдЖрдИрдбреА рдХреА рдПрдХ рд╕рд░рдгреА рд╕реНрдХреНрд▓рд╛рдЗрдЯ рдФрд░ рдорд╛рдИрдПрд╕рдХреНрдпреВрдПрд▓ рдХреЗ рд▓рд┐рдП рд╡рд╛рдкрд╕ рдХрд░ рджреА рдЬрд╛рддреА рд╣реИ, рдЬрдмрдХрд┐ рд╕рднреА рдХреА рдПрдХ рд╕рд░рдгреА рдбрд╛рд▓реА рдЧрдИ рдЖрдИрдбреА PostgreSQL рдХреЗ рд╕рд╛рде рд╡рд╛рдкрд╕ рдХрд░ рджреА рдЬрд╛рддреА рд╣реИ)ред

рдкреНрд░рд▓реЗрдЦрди рдХреЗ рдЕрдиреБрд╕рд╛рд░, MySQL рдореЗрдВ INSERT ... ON DUPLICATE KEY UPDATE рд╕рд┐рдВрдЯреИрдХреНрд╕ рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╡реНрдпрд╡рд╣рд╛рд░ рд╣реИ (http://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html):

ON DUPLICATE KEY UPDATE рдХреЗ рд╕рд╛рде, рдкреНрд░рддрд┐ рдкрдВрдХреНрддрд┐ рдкреНрд░рднрд╛рд╡рд┐рдд-рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХрд╛ рдорд╛рди 1 рд╣реИ рдпрджрд┐ рдкрдВрдХреНрддрд┐ рдХреЛ рдПрдХ рдирдИ рдкрдВрдХреНрддрд┐ рдХреЗ рд░реВрдк рдореЗрдВ рдбрд╛рд▓рд╛ рдЧрдпрд╛ рд╣реИ, 2 рдпрджрд┐ рдХреЛрдИ рдореМрдЬреВрджрд╛ рдкрдВрдХреНрддрд┐ рдЕрдкрдбреЗрдЯ рдХреА рдЧрдИ рд╣реИ, рдФрд░ 0 рдпрджрд┐ рдХреЛрдИ рдореМрдЬреВрджрд╛ рдкрдВрдХреНрддрд┐ рдЗрд╕рдХреЗ рд╡рд░реНрддрдорд╛рди рдорд╛рдиреЛрдВ рдкрд░ рд╕реЗрдЯ рд╣реИред

PostgreSQL рдореЗрдВ рд░рд╣рддреЗ рд╣реБрдП (http://www.postgresql.org/docs/9.5/static/sql-insert.html):

рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рдкреВрд░рд╛ рд╣реЛрдиреЗ рдкрд░, INSERT рдХрдорд╛рдВрдб рдлреЙрд░реНрдо рдХрд╛ рдХрдорд╛рдВрдб рдЯреИрдЧ рд▓реМрдЯрд╛рддрд╛ рд╣реИ

INSERT oid count

рдЧрд┐рдирддреА рд╕рдореНрдорд┐рд▓рд┐рдд рдпрд╛ рдЕрджреНрдпрддрди рдХреА рдЧрдИ рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рд╣реИред рдпрджрд┐ рдЧрд┐рдирддреА рдареАрдХ рдПрдХ рд╣реИ, рдФрд░ рд▓рдХреНрд╖реНрдп рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ OIDs рд╣реИрдВ, рддреЛ oid рд╕рдореНрдорд┐рд▓рд┐рдд рдкрдВрдХреНрддрд┐ рдХреЛ рдЕрд╕рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ OID рд╣реИред рдЕрджреНрдпрддрди рдХреЗ рдмрдЬрд╛рдп рдПрдХрд▓ рдкрдВрдХреНрддрд┐ рдХреЛ рд╕рдореНрдорд┐рд▓рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдерд╛ред рдЕрдиреНрдпрдерд╛ рдУрдб рд╢реВрдиреНрдп рд╣реИред

рдпрджрд┐ INSERT рдХрдорд╛рдВрдб рдореЗрдВ рдПрдХ рд░рд┐рдЯрд░реНрдирд┐рдВрдЧ рдХреНрд▓реЙрдЬ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдкрд░рд┐рдгрд╛рдо рдПрдХ рд╕реЗрд▓реЗрдХреНрдЯ рд╕реНрдЯреЗрдЯрдореЗрдВрдЯ рдХреЗ рд╕рдорд╛рди рд╣реЛрдЧрд╛, рдЬрд┐рд╕рдореЗрдВ рд░рд┐рдЯрд░реНрдирд┐рдВрдЧ рд╕реВрдЪреА рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХреЙрд▓рдо рдФрд░ рдорд╛рди рд╣реЛрддреЗ рд╣реИрдВ, рдЬреЛ рдХрдорд╛рдВрдб рджреНрд╡рд╛рд░рд╛ рдбрд╛рд▓реА рдЧрдИ рдпрд╛ рдЕрдкрдбреЗрдЯ рдХреА рдЧрдИ рдкрдВрдХреНрддрд┐рдпреЛрдВ рдкрд░ рдЧрдгрдирд╛ рдХреА рдЬрд╛рддреА рд╣реИред

рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╡рд╛рдкрд╕реА рдореВрд▓реНрдпреЛрдВ рдХреЛ RETURNING рдХреНрд▓реЙрдЬ рдХреЗ рд╕рд╛рде рдмрджрд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рд╡рд┐рдЪрд╛рд░?

рдореИрдВрдиреЗ рдмрдВрджрд░ рдХреЛ рд╕рдореНрдорд┐рд▓рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП "рдСрдирдХреЙрдиреНрдлреНрд▓рд┐рдХреНрдЯ" рд╡рд┐рдзрд┐ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП Client_PG рдХреЛ рдкреИрдЪ рдХрд┐рдпрд╛ред рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рд╣рдо рдЬреАрдердм рдУрде рдХреНрд░реЗрдбреЗрдВрд╢рд┐рдпрд▓реНрд╕ рдХреЛ рдЕрдкреНрд╕рд░реНрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рд╣рдо рдЗрд╕ рддрд░рд╣ рд╕реЗ рдХреНрд╡реЗрд░реА рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ:

const profile = {
    access_token: "blah blah",
    username: "foobar",
    // ... etc
  }

  const oauth = {
    uid: "13344398",
    provider: "github",
    created_at: new Date(),
    updated_at: new Date(),
    info: profile,
  };

  // todo: add a "timestamp" method

const insert = knex("oauths").insert(oauth).onConflict(["provider", "uid"],{
  info: profile,
  updated_at: new Date(),
});

console.log(insert.toString())

рд╕реНрддрдВрдн рдирд╛рдореЛрдВ рдХреА рд╕рд░рдгреА рд╡рд┐рд╢рд┐рд╖реНрдЯрддрд╛ рдмрд╛рдзрд╛ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рддреА рд╣реИред

insert into "authentications" ("created_at", "info", "provider", "uid", "updated_at") values ('2016-02-14T14:42:18.342+08:00', '{\"access_token\":\"blah blah\",\"username\":\"foobar\"}', 'github', '13344398', '2016-02-14T14:42:18.342+08:00') on conflict ("provider", "uid")  do update set "info" = '{\"access_token\":\"blah blah\",\"username\":\"foobar\"}', "updated_at" = '2016-02-14T14:42:18.343+08:00'

рд╕рд╛рд░ рджреЗрдЦреЗрдВ: рдмрдВрджрд░ рдкреИрдЪ рдХреЗ рд▓рд┐рдП https://gist.github.com/hayeah/1c8d642df5cfeabc2a5b ред

рдпрд╣ рдПрдХ рд╕реБрдкрд░ рд╣реИрдХреА рдкреНрд░рдпреЛрдЧ рд╣реИ... рдЗрд╕рд▓рд┐рдП рдЕрдкрдиреЗ рдкреНрд░реЛрдбрдХреНрд╢рди рдХреЛрдб рдореЗрдВ рдордВрдХреА рдкреИрдЪ рдХреЛ рдмрд┐рд▓реНрдХреБрд▓ рдХреЙрдкреА рдФрд░ рдкреЗрд╕реНрдЯ рди рдХрд░реЗрдВ: p

рдЬреНрдЮрд╛рдд рд╕рдорд╕реНрдпрд╛рдПрдВ:

  • QueryBuilder рдкрд░ рдордВрдХреА рдкреИрдЪ рд╕рднреА рдмреЛрд▓рд┐рдпреЛрдВ рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░рддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ Client_PG рдмрд┐рд▓реНрдбрд░ рдХрд╛ рд╡рд┐рд╢реЗрд╖рдЬреНрдЮ рдирд╣реАрдВ рд╣реИред
  • count = count + 1 рдЬреИрд╕реЗ рдХрдЪреНрдЪреЗ рдЕрдкрдбреЗрдЯ рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ
  • рдпрджрд┐ рдХреНрд╡реЗрд░реА рд╡рд┐рдзрд┐ рд╕рдореНрдорд┐рд▓рд┐рдд рдирд╣реАрдВ рд╣реИ, рддреЛ рд╕рдВрднрд╡рддрдГ onConflict рдХреЛ рдлреЗрдВрдХ рджреЗрдирд╛ рдЪрд╛рд╣рд┐рдПред

рдкреНрд░рддрд┐рдкреБрд╖реНрдЯрд┐?

@hayeah рдореБрдЭреЗ рдЖрдкрдХрд╛ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдкрд╕рдВрдж рд╣реИ рдФрд░ рдпрд╣ рдкреЛрд╕реНрдЯрдЧреНрд░реЗрдЬ рдХреЗ рдЕрдиреБрд░реВрдк рд╣реИред рдореИрдВ рдПрдХ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рдЖрдкрдХреЗ рдордВрдХреА рдкреИрдЪ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рдиреЗ рдЬрд╛ рд░рд╣рд╛ рд╣реВрдВ, рдпрд╣ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдХреНрдпрд╛ рдореИрдВ рдЕрдиреБрднрд╡рдЬрдиреНрдп рд░реВрдк рд╕реЗ рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рдмрддрд╛рдП рдЧрдП рдореБрджреНрджреЛрдВ рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдХрд┐рд╕реА рдЕрдиреНрдп рдореБрджреНрджреЗ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛ рд╕рдХрддрд╛ рд╣реВрдВред

рд╕рд┐рдВрдЯреИрдХреНрд╕ рд╕реБрдЭрд╛рд╡: knex('table').upsert(['col1','col2']).insert({...}).update({...}); рдЬрд╣рд╛рдВ upsert рдХрдВрдбреАрд╢рди рд╕реНрдЯреЗрдЯрдореЗрдВрдЯ рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реЛрдЧрд╛ред рдЗрд╕ рддрд░рд╣ рдпрд╣ рдбреАрдмреА рд╡рд┐рд╢рд┐рд╖реНрдЯ рдирд╣реАрдВ рд╣реИред

upserts рдХреЗ рд╡рд┐рднрд┐рдиреНрди рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рд╕рд╛рд░рд╛рдВрд╢ https://en.wikipedia.org/wiki/Merge_ (SQL) рдкрд░ рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдореБрдЭреЗ рдпрд╣ рдХреНрд╖рдорддрд╛ рд░рдЦрдиреЗ рдореЗрдВ рднреА рджрд┐рд▓рдЪрд╕реНрдкреА рд╣реИред рдХреЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ: рдПрдХ рдРрд╕реА рдкреНрд░рдгрд╛рд▓реА рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рдирд╛ рдЬреЛ рдмрд╛рд╣рд░реА рд╕реЗрд╡рд╛ рд╕реЗ рдмрд╣реБрдд рд╕рд╛рд░реЗ рдмрд╛рд╣рд░реА рдбреЗрдЯрд╛ рдкрд░ рдирд┐рд░реНрднрд░ рд╣реЛ; рдореИрдВ рд╕рдордп-рд╕рдордп рдкрд░ рдЗрд╕реЗ рдбреЗрдЯрд╛ рдХреЗ рд▓рд┐рдП рдорддрджрд╛рди рдХрд░рддрд╛ рд╣реВрдВ рдЬрд┐рд╕реЗ рдореИрдВ рд╕реНрдерд╛рдиреАрдп MySQL рдбреАрдмреА рдореЗрдВ рд╕рд╣реЗрдЬрддрд╛ рд╣реВрдВред рд╢рд╛рдпрдж рдЕрднреА рдХреЗ рд▓рд┐рдП knex.raw рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реЛрдВрдЧреЗред

рд░реБрдЪрд┐ рднреА рд╣реИ, рд▓реЗрдХрд┐рди рдореЗрд░реЗ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдЗрд╕реЗ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА рдЬреЛ рд╕рдВрдШрд░реНрд╖реЛрдВ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рди рд╣реЛ, рдХреНрдпреЛрдВрдХрд┐ рдХреЙрд▓рдо рдореЗрдВ рд╣рдореЗрд╢рд╛ 'рдЕрджреНрд╡рд┐рддреАрдп' рдмрд╛рдзрд╛рдПрдВ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИрдВ - рдпрджрд┐ рд╡реЗ рдореМрдЬреВрдж рд╣реИрдВ рддреЛ рдХреНрд╡реЗрд░реА рд╕реЗ рдореЗрд▓ рдЦрд╛рдиреЗ рд╡рд╛рд▓реА рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпреЛрдВ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░реЗрдВ, рдЕрдиреНрдпрдерд╛ рдбрд╛рд▓реЗрдВ рдирдИ рдкрдВрдХреНрддрд┐рдпрд╛рдБред

@haywirez рдореИрдВ рдЙрддреНрд╕реБрдХ рд╣реВрдВ рдХрд┐ рдХреЛрдИ рдЕрдиреВрдареА рдмрд╛рдзрд╛ рдХреНрдпреЛрдВ рдирд╣реАрдВ рд╣реИ? рдХреНрдпрд╛ рдЖрдк рджреМрдбрд╝ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЗ рд╕рдВрдкрд░реНрдХ рдореЗрдВ рдирд╣реАрдВ рдЖрдПрдВрдЧреЗ?

@hayeah рдореЗрд░реЗ рдкрд╛рд╕ рд╕рдордп-рд╡рд┐рдВрдбреЛ рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЙрдкрдпреЛрдЧ рдХрд╛ рдорд╛рдорд▓рд╛ рд╣реИ, рдЬреЛ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпреЛрдВ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддрд╛ рд╣реИ рдЬрд┐рдирдХрд╛ рдореВрд▓реНрдп рдХрд┐рд╕реА рджрд┐рдП рдЧрдП рджрд┐рди рд╕реЗ рдЬреБрдбрд╝рд╛ рд╣реЛрддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЙрди рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпреЛрдВ рдХреЛ рд╕рдореНрдорд┐рд▓рд┐рдд рдФрд░ рдЕрджреНрдпрддрди рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдЬрд┐рдирдореЗрдВ рдорд┐рд▓рд╛рди (рджрд┐рди) рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк рдХреА "рд╕рдВрдпреБрдХреНрдд рдХреБрдВрдЬреА" рд╣реИ, рдФрд░ рдЕрдиреНрдп рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдореЗрдВ рдкреАрдХреЗ рдХреЗ рдЕрдиреБрд░реВрдк рджреЛ рдЕрдиреНрдп рдЖрдИрдбреА рд╣реИрдВред 24 рдШрдВрдЯреЗ рдХреА рд╡рд┐рдВрдбреЛ рдХреЗ рднреАрддрд░, рдореБрдЭреЗ рдпрд╛ рддреЛ рдЙрдиреНрд╣реЗрдВ рд╕рдореНрдорд┐рд▓рд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛, рдпрд╛ рдЙрдиреНрд╣реЗрдВ рдирд╡реАрдирддрдо рдЧрдгрдирд╛рдУрдВ рдХреЗ рд╕рд╛рде рдЕрдкрдбреЗрдЯ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред

рдпрд╣ рдПрдХ рдмрдбрд╝реА рд╡рд┐рд╢реЗрд╖рддрд╛ рд╣реЛрдЧреА!

рд╣рд╛рдп рд╕рдм рд▓реЛрдЧ рдЬрд┐рдиреНрд╣реЛрдВрдиреЗ рдХрднреА рдпрд╣рд╛рдВ рдЯрд┐рдкреНрдкрдгреА рдХреА рд╣реИред рдореИрдВ рдПрдХ рдкреАрдЖрд░ рдЬреЛрдбрд╝ рд░рд╣рд╛ рд╣реВрдБ рдХреГрдкрдпрд╛ рд▓реЗрдмрд▓ рд▓рдЧрд╛рдПрдБред

рдЗрд╕ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдкреАрдЖрд░ рд▓реЗрдиреЗ рдореЗрдВ рдЦреБрд╢реА рд╣реБрдИ, рд▓реЗрдХрд┐рди рдореИрдВ рдпрд╣рд╛рдВ рд╡рд╛рдВрдЫрд┐рдд рдПрдкреАрдЖрдИ рдХреА рдЪрд░реНрдЪрд╛ рдкрд╣рд▓реЗ рджреЗрдЦрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред

рдкреБрдирд╢реНрдЪ.

^ рд╕рд╣рдорддред

рдореИрдВ рдЗрд╕ рддрд░рд╣ рдХреА рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдХреЛ рд╣рдЯрд╛рдиреЗ рдЬрд╛ рд░рд╣рд╛ рд╣реВрдВ, рдЕрдЧрд░ рдЖрдк рдПрдХ +1 рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рддреЛ рдЫреЛрдЯреА рдЗрдореЛрдЬреА рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рд╕рд╛рде рдРрд╕рд╛ рдХрд░реЗрдВред

рдореЗрд░реЗ рдкрд╛рд╕ @willfarrell рдФрд░ @hayeah рдХреЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ рдХреЙрд▓рдо рдкреНрд░рддрд┐рдмрдВрдзреЛрдВ рдХреА рд╕рд░рдгреА рдХреЗ рд╕рд╛рде рдХреБрдЫ рд╕рдорд╕реНрдпрд╛ рд╣реИред рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдирд╣реАрдВ рд╣реИрдВ рдХрд┐ рдпреЗ рдЙрджрд╛рд╣рд░рдг json рд╕рдВрдкрддреНрддрд┐рдпреЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдХреНрдпрд╛ рдХреЛрдИ рдХрд╛рд░рдг рд╣реИ рдХрд┐ рдЗрдирдореЗрдВ рд╕реЗ рдХрд┐рд╕реА рднреА рдкреНрд░рд╕реНрддрд╛рд╡ рдореЗрдВ рд░рд┐рдХреЙрд░реНрдб рд╕реЗ рдорд┐рд▓рд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдерди/рдЙрдЪрд┐рдд "рдкреНрд░рд╢реНрди" рд╢рд╛рдорд┐рд▓ рдирд╣реАрдВ рд╣реИрдВ?

рдкреНрд░рд╕реНрддрд╛рд╡ 1

knex('table')
  .where('id', '=', data.id)
  .upsert(data)

рдкреНрд░рд╕реНрддрд╛рд╡ 2

knex('table')
  .upsertQuery(knex => {
    return knex('table')
      .where('id', '=', data.id)
  })
  .upsertUpdate(knex => {
    return knex('table')
      .insert(data)
  })

рдкреНрд░рд╕реНрддрд╛рд╡ 3

knex('table')
  .where('id', '=', data.id)
  .insert(data)
  .upsert() // or .onConflictDoUpdate()

рдореИрдВ 3 рдЬреИрд╕реА рдХрд┐рд╕реА рдЪреАрдЬрд╝ рдХреА рдУрд░ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдЭреБрдХ рд░рд╣рд╛ рд╣реВрдБред

рдмрд╕ рдпрд╣рд╛рдБ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ mongodb рдпрд╣ рдХреИрд╕реЗ рдХрд░рддрд╛ рд╣реИ ред

db.collection.update(
   <query>,
   <update>,
   {
     upsert: <boolean>,
     multi: <boolean>,
     writeConcern: <document>
   }
)

@reggi рдореБрдЭреЗ рд╡рд┐рд╢реНрд╡рд╛рд╕ рд╣реИ рдХрд┐ рдореЗрд░рд╛ рдмрдВрджрд░ рдкреИрдЪ where рдХреЗ рд╕рд╛рде рд╕рдВрдЧрдд рд╣реИ ...

@reggi рдореБрдЭреЗ рдЖрдкрдХреА рдмрд╛рдд рджрд┐рдЦрд╛рдИ рдирд╣реАрдВ рджреЗ рд░рд╣реА рд╣реИред
рдХреНрдпрд╛ рдЖрдк рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рдмрддрд╛ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ @willfarrell рдФрд░ @hayeah рдХреЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕реЗ рдХреМрди рд╕реА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдЧрд╛рдпрдм рд╣реИред
рдЖрдкрдХреЛ where рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреНрдпреЛрдВ рд╣реИ?
рдпрд╣ рд╕рд┐рд░реНрдл рдПрдХ insert рдСрдкрд░реЗрд╢рди рд╣реИред

@reggi рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЧрдпрд╛ рдореЛрдВрдЧреЛрдбреАрдмреА рдЙрджрд╛рд╣рд░рдг рдкрдврд╝рддрд╛ рд╣реИ "рдкрд╣рд▓реЗ рдХрд╣рд╛рдВ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ ... .
рддреЛ, рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ, рдЖрдк SQL рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рд▓рд╛рдЧреВ рд╣реЛрдиреЗ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд▓рдЧ "рдЕрдкрд░реНрдЯ" рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВред

рдореИрдВ рдЗрд╕ рдПрдкреАрдЖрдИ рдХрд╛ рдкреНрд░рд╕реНрддрд╛рд╡ рджреВрдВрдЧрд╛:

knex.createTable('test')
   .bigserial('id')
   .varchar('unique').notNull().unique()
   .varchar('whatever')

knex.table('test').insert(object, { upsert: ['unique'] })

.insert() рдлрд╝рдВрдХреНрд╢рди рджреВрд╕рд░реЗ рдкреИрд░рд╛рдореАрдЯрд░ рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░реЗрдЧрд╛ред
рдпрджрд┐ рдпрд╣ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╣реИ, рддреЛ рдпрд╣ рдкреБрд░рд╛рдирд╛ returning рдкреИрд░рд╛рдореАрдЯрд░ рд╣реИред
рдпрджрд┐ рдпрд╣ рдПрдХ рд╡рд╕реНрддреБ рд╣реИ, рддреЛ рдпрд╣ рдПрдХ options рдкреИрд░рд╛рдореАрдЯрд░ рд╣реИ рдЬрд┐рд╕рдореЗрдВ options.returning рдФрд░ options.upsert рд╣реИ, рдЬрд╣рд╛рдВ options.upsert рдЕрджреНрд╡рд┐рддреАрдп рдХреБрдВрдЬрд┐рдпреЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рд╣реИ (рд╣реЛ рд╕рдХрддрд╛ рд╣реИ > 1 рдЗрдВрдЪ) рдПрдХ рдпреМрдЧрд┐рдХ рдЕрджреНрд╡рд┐рддреАрдп рдХреБрдВрдЬреА рдмрд╛рдзрд╛ рдХрд╛ рдорд╛рдорд▓рд╛)ред
рдлрд┐рд░ рдПрдХ SQL рдХреНрд╡реЗрд░реА рдЙрддреНрдкрдиреНрди рд╣реЛрддреА рд╣реИ рдЬреЛ рдкреНрд░рд╛рдердорд┐рдХ рдХреБрдВрдЬреА рдФрд░ рд╕рднреА options.upsert рдХреБрдВрдЬрд┐рдпреЛрдВ рдХреЛ object ( clone(object) && delete cloned_object.id && delete cloned_object.unique рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ) рд╕реЗ рдмрд╛рд╣рд░ рдХрд░ рджреЗрддреА рд╣реИ рдФрд░ рдлрд┐рд░ рдЙрд╕ cloned_object рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреА рд╣реИ SQL рдХреНрд╡реЗрд░реА рдХреЗ рджреВрд╕рд░реЗ рднрд╛рдЧ рдореЗрдВ SET рдХреНрд▓реЙрдЬ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рд╛рдердорд┐рдХ (рдФрд░ рдЕрджреНрд╡рд┐рддреАрдп) рдХреБрдВрдЬрд┐рдпрд╛рдБ: ... ON CONFLICT DO UPDATE SET [iterate cloned_object] ред

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╡рд░реНрддрдорд╛рди рдПрдкреАрдЖрдИ рдХреЗ рд╕рд╛рде рд╕рдЬрд╛рддреАрдп рд╕рдмрд╕реЗ рд╕рд░рд▓ рдФрд░ рд╕реНрдкрд╖реНрдЯ рд╕рдорд╛рдзрд╛рди рд╣реЛрдЧрд╛ред

@slavafomin @ScionOfBytes рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдПрдкреАрдЖрдИ рдкрд░ рднреА рдЕрднреА рддрдХ рд╕рд╣рдорддрд┐ рдирд╣реАрдВ рдмрдиреА рд╣реИред рдпрд╣ рдЕрдЧрд▓рд╛ рдХрджрдо рд╣реЛрдЧрд╛ рдФрд░ рдлрд┐рд░ рдЬреЛ рдХреЛрдИ рдЗрд╕реЗ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдкрд╕рдВрдж рдХрд░рддрд╛ рд╣реИ рд╡рд╣ рдРрд╕рд╛ рдХрд░ рд╕рдХрддрд╛ рд╣реИред рддреЛ рдХреЛрдИ рдЦрдмрд░ рдирд╣реАрдВред

рдкреБрдирд╢реНрдЪ рдпрджрд┐ рдЗрд╕ рдереНрд░реЗрдб рдХреЛ рд╕рдорд╛рдЪрд╛рд░ рдЕрдиреБрд░реЛрдз рд╕реНрдкреИрдо рдФрд░ рдЕрдиреНрдп рдХрдо рд╕рдВрдмрдВрдзрд┐рдд рд╕рдВрджреЗрд╢реЛрдВ рд╕реЗ рднрд░рдиреЗ рд╕реЗ рд░реЛрдХрдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдирд╣реАрдВ рд╣реИ, рддреЛ рдореИрдВрдиреЗ рд╕рдорд╛рдЪрд╛рд░ рдХреЗ рд▓рд┐рдП рдХрд┐рд╕реА рднреА рдЕрддрд┐рд░рд┐рдХреНрдд рдЕрдиреБрд░реЛрдз рдХреЛ рд╣рдЯрд╛рдирд╛ рд╢реБрд░реВ рдХрд░ рджрд┐рдпрд╛ред

@ рдЖрдорд┐рд░-рдореИрдВ рд╕рд╣рдордд рд╣реВрдВ, рд▓реЗрдХрд┐рди рдЗрд╕ рдореБрджреНрджреЗ рдХрд╛ рд╡рд┐рд╖рдп рдКрдкрд░реА рдХреНрд╖рдорддрд╛ рд╣реИред

рдЖрдИрдПрдордУ, рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рдорд╕реНрдпрд╛ рдПрдкреАрдЖрдИ рдирд╣реАрдВ рд╣реИ, рдмрд▓реНрдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдЕрдкреНрд╕рд░реНрдЯ рдХрд░рдиреЗ рдХрд╛ рдЕрд╕рд╛рдорд╛рдиреНрдп рддрд░реАрдХрд╛ рд╣реИред

MySQL (рдСрди рдбреБрдкреНрд▓реАрдХреЗрдЯ рдХреА рдЕрдкрдбреЗрдЯ) рдФрд░ рдкреЛрд╕реНрдЯрдЧреНрд░реЗрдПрд╕рдХреНрдпреВрдПрд▓ 9.5+ (рдСрди рдХреЙрдиреНрдлреНрд▓рд┐рдХреНрдЯ рдбреВ рдЕрдкрдбреЗрдЯ) рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдЕрдкреНрд╕рд░реНрдЯ рдХреЛ рд╕рдкреЛрд░реНрдЯ рдХрд░рддреЗ рд╣реИрдВред

рдПрдордПрд╕рдПрд╕рдХреНрдпреВрдПрд▓ рдФрд░ рдУрд░реЗрдХрд▓ рдЗрд╕реЗ рдорд░реНрдЬ рдХреНрд▓реЙрдЬ рдХреЗ рд╕рд╛рде рд╕рдорд░реНрдерди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдХреНрдиреЗрдХреНрд╕ рдХреЛ рдХреНрд╡реЗрд░реА рдмрдирд╛рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдВрдШрд░реНрд╖ рдХреЙрд▓рдо рдХреЗ рдирд╛рдо рдкрддрд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред

-- in this case the conflict column is 'a'
merge into target
using (values (?)) as t(a)
on (t.a = target.a)
when matched then
  update set b = ?
when not matched then
  insert (a, b) values (?, ?);

рд▓реЗрдХрд┐рди SQLite рдирд╣реАрдВ рдХрд┐рдпрд╛ред рдЕрдкрд░рд░реНрдЯ рдХрд╛ рдЕрдиреБрдХрд░рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдореЗрдВ рджреЛ рдкреНрд░рд╢реНрдиреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ

-- 'a' is the conflict column
insert or ignore into target (a, b) values (?, ?);
update target set b = ?2 where changes() = 0 and a = ?1;

рдпрд╛ INSERT OR REPLACE , рдЙрд░реНрдл REPLACE . рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВ

-- replace will delete the matched row then add a new one with the given data
replace into target (a, b) values (?, ?);

рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рдпрджрд┐ рд▓рдХреНрд╖реНрдп рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ a рдФрд░ b рд╕реЗ рдЕрдзрд┐рдХ рд╕реНрддрдВрдн рд╣реИрдВ, рддреЛ рдЙрдирдХреЗ рдорд╛рди рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд╕реЗ рдмрджрд▓ рджрд┐рдП рдЬрд╛рдПрдВрдЧреЗ

insert or replace into target (a, b, c) values (?, ?, (select c from target where a = ?1))

рд╕реАрдЯреАрдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдФрд░ рд╕рдорд╛рдзрд╛рди, рдпрд╣ рд╕реНрдЯреИрдХ рдУрд╡рд░рдлреНрд▓реЛ рдЙрддреНрддрд░ рджреЗрдЦреЗрдВ

рдореИрдВ рдЗрд╕ рдореБрджреНрджреЗ рдкрд░ рдХрдИ рдмрд╛рд░ рдПрдХ knex- рдЖрдзрд╛рд░рд┐рдд Postgres upsert рдХреА рддрд▓рд╛рд╢ рдореЗрдВ рдЖрдпрд╛ рд╣реВрдБред рдЕрдЧрд░ рдХрд┐рд╕реА рдФрд░ рдХреЛ рдЗрд╕рдХреА рдЬрд╝рд░реВрд░рдд рд╣реИ, рддреЛ рдпрд╣ рдХреИрд╕реЗ рдХрд░рдирд╛ рд╣реИред рдореИрдВрдиреЗ рдЗрд╕реЗ рдПрдХрд▓ рдФрд░ рд╕рдордЧреНрд░ рдЕрджреНрд╡рд┐рддреАрдп рдХреБрдВрдЬреА рджреЛрдиреЛрдВ рдХреЗ рд╡рд┐рд░реБрджреНрдз рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рд╣реИред

рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдирд╛

рдиреАрдЪреЗ рджреА рдЧрдИ рддрд╛рд▓рд┐рдХрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдЕрджреНрд╡рд┐рддреАрдп рдХреБрдВрдЬреА рдмрд╛рдзрд╛ рдмрдирд╛рдПрдВред рдореБрдЭреЗ рдПрдХ рд╕рдордЧреНрд░ рдХреБрдВрдЬреА рдмрд╛рдзрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдереА:

table.unique(['a', 'b'])

рдХрд╛рд░реНрдпрдХреНрд░рдо

(рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ: рдХрдЪреНрдЪреЗ рдкреИрд░рд╛рдореАрдЯрд░ рдмрд╛рдЗрдВрдбрд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрджреНрдпрддрди)

const upsert = (params)=> {
  const {table, object, constraint} = params;
  const insert = knex(table).insert(object);
  const update = knex.queryBuilder().update(object);
  return knex.raw(`? ON CONFLICT ${constraint} DO ? returning *`, [insert, update]).get('rows').get(0);
};

рдкреНрд░рдпреЛрдЧ

const objToUpsert = {a:1, b:2, c:3}

upsert({
    table: 'test',
    object: objToUpsert,
    constraint: '(a, b)',
})

рдпрджрд┐ рдЖрдкрдХреА рдмрд╛рдзрд╛ рд╕рдордЧреНрд░ рдирд╣реАрдВ рд╣реИ, рддреЛ рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ, рд╡рд╣ рдПрдХ рдкрдВрдХреНрддрд┐ рдХреЗрд╡рд▓ constraint: '(a)' рд╣реЛрдЧреАред

рдпрд╣ рдпрд╛ рддреЛ рдЕрджреНрдпрддрди рд╡рд╕реНрддреБ рдпрд╛ рд╕рдореНрдорд┐рд▓рд┐рдд рд╡рд╕реНрддреБ рд▓реМрдЯрд╛рдПрдЧрд╛ред

рд╕рдордЧреНрд░ рдЕрд╢рдХреНрдд рд╕реВрдЪрдХрд╛рдВрдХреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рдиреЛрдЯ

рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдПрдХ рд╕рдордЧреНрд░ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рд╣реИ (a,b) рдФрд░ b рдЕрд╢рдХреНрдд рд╣реИ, рддреЛ рдореВрд▓реНрдпреЛрдВ (1, NULL) рдФрд░ (1, NULL) рдХреЛ Postgres рджреНрд╡рд╛рд░рд╛ рдкрд╛рд░рд╕реНрдкрд░рд┐рдХ рд░реВрдк рд╕реЗ рдЕрджреНрд╡рд┐рддреАрдп рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ (рдореБрдЭреЗ рдпрд╣ рдирд╣реАрдВ рдорд┐рд▓рд╛ рджреЛрдиреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ)ред рдпрджрд┐ рдпрд╣ рдЖрдкрдХрд╛ рдЙрдкрдпреЛрдЧ рдорд╛рдорд▓рд╛ рд╣реИ, рддреЛ рдЖрдкрдХреЛ рдЖрдВрд╢рд┐рдХ рдЕрджреНрд╡рд┐рддреАрдп рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА рдФрд░ рдлрд┐рд░ рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдХрд┐рд╕ рдмрд╛рдзрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ, рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкреНрд╕рд░реНрдЯ рд╕реЗ рдкрд╣рд▓реЗ рд╢реВрдиреНрдп рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг рдХрд░реЗрдВред рдЖрдВрд╢рд┐рдХ рдЕрджреНрд╡рд┐рддреАрдп рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдмрдирд╛рдиреЗ рдХрд╛ рддрд░реАрдХрд╛ рдпрд╣рд╛рдВ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ: CREATE UNIQUE INDEX unique_index_name ON table (a) WHERE b IS NULL ред рдпрджрд┐ рдЖрдкрдХрд╛ рдкрд░реАрдХреНрд╖рдг рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ b рд╢реВрдиреНрдп рд╣реИ, рддреЛ рдЖрдкрдХреЛ рдЗрд╕ рдмрд╛рдзрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЕрдкрдиреЗ рдЕрдкреНрд╕рд░реНрдЯ рдореЗрдВ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА: constraint: '(a) WHERE b IS NULL' ред рдпрджрд┐ a рднреА рд╢реВрдиреНрдп рд╣реИ, рддреЛ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЖрдкрдХреЛ 3 рдЕрджреНрд╡рд┐рддреАрдп рд╕реВрдЪрдХрд╛рдВрдХ рдФрд░ 4 if/else рд╢рд╛рдЦрд╛рдУрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА (рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рдореЗрд░рд╛ рдЙрдкрдпреЛрдЧ рдорд╛рдорд▓рд╛ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ)ред

рдпрд╣рд╛рдБ рд╕рдВрдХрд▓рд┐рдд рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╣реИ ред

рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдХрд┐рд╕реА рдХреЛ рдпрд╣ рдЙрдкрдпреЛрдЧреА рд▓рдЧреЗрдЧрд╛ред @elhigu knex().update(object) рдХреЗ рдЙрдкрдпреЛрдЧ рдкрд░ рдХреЛрдИ рдЯрд┐рдкреНрдкрдгреА? (рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ: рдХреЛрдИ рдмрд╛рдд рдирд╣реАрдВ - рдЪреЗрддрд╛рд╡рдиреА рджреЗрдЦреА - рдЕрдм knex.queryBuilder() рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ)

@timhuff рдЕрдЪреНрдЫрд╛ рд▓рдЧ рд░рд╣рд╛ рд╣реИ, рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЪреАрдЬ рдореВрд▓реНрдп рдмрд╛рдзреНрдпрдХрд╛рд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рдХреНрд╡реЗрд░реА рдХреЛ рдХрдЪреНрдЪреЗ рдореЗрдВ рдкрд╛рд╕ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдЕрдиреНрдпрдерд╛ query.toString() рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреНрд╡реЗрд░реА рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рднрд╛рдЧ рдХреЛ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдпрд╣ рд╕рдВрднрд╛рд╡рд┐рдд рдирд┐рд░реНрднрд░рддрд╛ рдЗрдВрдЬреЗрдХреНрд╢рди рдЫреЗрдж рдХреЛ рдЦреЛрд▓рддрд╛ рд╣реИ (queryBuilder.toString() рдбреНрд░рд╛рдЗрд╡рд░ рдХреЗ рд▓рд┐рдП рдмрд╛рдЗрдВрдбрд┐рдВрдЧ рдХреЗ рд░реВрдк рдореЗрдВ рдкреИрд░рд╛рдореАрдЯрд░ рдкрд╛рд╕ рдХрд░рдиреЗ рдЬрд┐рддрдирд╛ рд╕реБрд░рдХреНрд╖рд┐рдд рдирд╣реАрдВ рд╣реИ) ..

@elhigu рд░реБрдХреЛ ... query.toString() рдмрд╛рдЗрдВрдбрд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ? рдХреНрдпрд╛ рдЖрдк рдореБрдЭреЗ рдЙрд╕ рд╕рдВрд╢реЛрдзрди рдХрд╛ рдПрдХ рдореЛрдЯрд╛ рдЙрджрд╛рд╣рд░рдг рджреЗ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд┐рд╕рдХреА рдЖрдк рдЕрдиреБрд╢рдВрд╕рд╛ рдХрд░ рд░рд╣реЗ рд╣реИрдВ? рдореИрдВ... рдЕрджреНрдпрддрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рд╕рд╛рд░реЗ рдХреЛрдб рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред

рд░реЙ рдмрд╛рдЗрдВрдбрд┐рдВрдЧ рд▓реЗрдмрд▓ рд╡рд╛рд▓реЗ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рдорд┐рд▓рд╛ред рдЕрдм рдЕрдкрдбреЗрдЯ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдореИрдВрдиреЗ рдЙрджрд╛рд╣рд░рдг рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рд╣реИред рдореБрдЭреЗ рд▓рдЧрд╛ рдХрд┐ query.toString рд╕реБрд░рдХреНрд╖рд┐рдд рд╣реИред "рдЕрд╕реБрд░рдХреНрд╖рд┐рдд рдкреНрд░рд╢реНрди рдХреИрд╕реЗ рдХрд░реЗрдВ" рдЬреИрд╕реЗ рдХреБрдЫ рд▓реЗрдмрд▓ рд╡рд╛рд▓реЗ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реАрдХрд░рдг рдХреЗ рдПрдХ рднрд╛рдЧ рдХреЛ рд░рдЦрдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ред рдХреЗрд╡рд▓ рдХреБрдЫ рд╣реА рд╕рдВрдЦреНрдпрд╛рдПрдВ рд╣реИрдВ рдФрд░ рдЗрд╕ рддрд░рд╣ рд▓реЛрдЧ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдпрд╣ рдЬрд╛рдирдХрд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ "рдЬрдм рддрдХ рдореИрдВ рдЗрди рдЪреАрдЬреЛрдВ рдХреЛ рдирд╣реАрдВ рдХрд░рддрд╛, рдореИрдВ рд╕реБрд░рдХреНрд╖рд┐рдд рд╣реВрдВ"ред

рдореИрдВрдиреЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЕрдкреНрд╕рд░реНрдЯ рдмрдирд╛рдпрд╛ рд╣реИ: https://gist.github.com/adnanoner/b6c53482243b9d5d5da4e29e109af9bd
рдпрд╣ рд╕рд┐рдВрдЧрд▓ рдФрд░ рдмреИрдЪ рдЕрдкреНрд╕рд░реНрдЯ рдХреЛ рд╣реИрдВрдбрд▓ рдХрд░рддрд╛ рд╣реИред рдореИрдВрдиреЗ рдЗрд╕реЗ @plurch рд╕реЗ рдереЛрдбрд╝рд╛ рд╕рд╛ рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд┐рдпрд╛ред рд╕реБрдзрд╛рд░ рдХреА рд╣рдореЗрд╢рд╛ рд╕рд░рд╛рд╣рдирд╛ рдХреА рдЬрд╛рддреА рд╣реИ :)

рдЗрд╕рдХреЗ рд▓рд╛рдпрдХ рдХреНрдпрд╛ рд╣реИ рдореИрдВ рдЗрд╕ рдкреНрд░рд╛рд░реВрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ:

рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ: рдЗрд╕реЗ рдЦреЛрдЬрдиреЗ рд╡рд╛рд▓реЗ рдХрд┐рд╕реА рднреА рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд▓рд┐рдП рд╕реБрд░рдХреНрд╖рд┐рдд рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ред рдзрдиреНрдпрд╡рд╛рдж @elhigu

const query = knex( 'account' ).insert( accounts );
const safeQuery = knex.raw( '? ON CONFLICT DO NOTHING', [ query ]);

@NicolajKN рдЖрдкрдХреЛ toString() рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЗрд╕рд╕реЗ рдХрдИ рдкреНрд░рдХрд╛рд░ рдХреА рд╕рдорд╕реНрдпрд╛рдПрдВ рд╣реЛ рд╕рдХрддреА рд╣реИрдВ рдФрд░ рдбреАрдмреА (рд╕рдВрднрд╛рд╡рд┐рдд рдПрд╕рдХреНрдпреВрдПрд▓ рдЗрдВрдЬреЗрдХреНрд╢рди рд╕реБрд░рдХреНрд╖рд╛ рдЫреЗрдж) рдХреЛ рдмрд╛рдЗрдВрдбрд┐рдВрдЧ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдореВрд▓реНрдпреЛрдВ рдХреЛ рдкрд╛рд░рд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

рд╡рд╣реА рдареАрдХ рд╕реЗ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдпрд╣ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реЛрдЧрд╛:

const query = knex('account').insert(accounts);
const safeQuery = knex.raw('? ON CONFLICT DO NOTHING', [query]);

рдЕрд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЗ рдХреА рд╣рдЯрд╛рдИ рдЧрдИ рдЪрд░реНрдЪрд╛ред

@elhigu рд╣реЛрд▓реНрдб рдСрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рд╕рдореНрдорд┐рд▓рд┐рдд рдХреНрд╡реЗрд░реА рдХреЛ рдмрдирд╛рдП рдЬрд╛рдиреЗ рдХреЗ рддреБрд░рдВрдд рдмрд╛рдж рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ? рдХреНрдпрд╛ рдпрд╣ рджреМрдбрд╝ рдХреА рд╕реНрдерд┐рддрд┐ рдирд╣реАрдВ рдмрдирд╛рддрд╛ рд╣реИ?

@cloutiertyler рдЖрдк рдореБрдЭрд╕реЗ рдмрд╛рдд рдирд╣реАрдВ рдХрд░ рд░рд╣реЗ рдереЗ, рд▓реЗрдХрд┐рди рд╢рд╛рдпрдж рдореИрдВ рдпрд╣рд╛рдВ рдХреБрдЫ рд╕рдордп @elhigu рдмрдЪрд╛ рд╕рдХрддрд╛ рд╣реВрдВред рдЗрдирдореЗрдВ рд╕реЗ рдХреЛрдИ рднреА рдкреНрд░рд╢реНрди рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдХрдерди knex('account').insert(accounts) рдПрдХ рдХреНрд╡реЗрд░реА рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рдЗрд╕реЗ рддрдм рддрдХ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрдм рддрдХ рдХрд┐ рдбреЗрдЯрд╛ рдХреЛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреЙрд▓ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП .then рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ)ред рд╡рд╣ рдЙрд╕реЗ knex.raw('? ON CONFLICT DO NOTHING', [query]) query.toString() рдХреЛ рдХреЙрд▓ рдХрд░реЗрдЧрд╛, рдЬреЛ рдХреЗрд╡рд▓ рдХреНрд╡реЗрд░реА рдХреЛ SQL рдХрдерди рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

@timhuff рдзрдиреНрдпрд╡рд╛рдж рдЯрд┐рдо, рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕реЗ рдРрд╕рд╛ рдХреБрдЫ рд╣реЛрдирд╛ рдерд╛, рд▓реЗрдХрд┐рди рдпрд╣ рдПрдХ рд╡рд╛рджреЗ рдХреЗ рд▓рд┐рдП рд╕рд╛рдорд╛рдиреНрдп рд╡реНрдпрд╡рд╣рд╛рд░ рдирд╣реАрдВ рд╣реИред рд╡рд╛рджреЛрдВ рдХреЛ рдЖрдорддреМрд░ рдкрд░ рд╕реГрдЬрди рдкрд░ рдХреНрд░рд┐рдпрд╛рдиреНрд╡рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдореЗрд░реЗ рдкреВрдЫрдиреЗ рдХрд╛ рдХрд╛рд░рдг рдпрд╣ рд╣реИ рдХрд┐ рдЬрдм рдореИрдВ рдЗрд╕ рдЕрдкреНрд╕рд░реНрдЯ рдХреЛ рдЪрд▓рд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддрд╛ рд╣реВрдВ рддреЛ рдореБрдЭреЗ рд╣рд░ рдмрд╛рд░ "рдХрдиреЗрдХреНрд╢рди рдЯрд░реНрдорд┐рдиреЗрдЯреЗрдб" рдХрд╣рдиреЗ рдореЗрдВ рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╣реЛ рд░рд╣реА рдереАрдВред рдПрдХ рдмрд╛рд░ рдЬрдм рдореИрдВрдиреЗ рдбрд╛рд▓рдиреЗ рдХреЛ рд╣рдЯрд╛рдиреЗ рдФрд░ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдХрдЪреНрдЪреА рдХреНрд╡реЗрд░реА рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рд┐рдЪ рдХрд┐рдпрд╛ рддреЛ рд╡реЗ рдЪрд▓реЗ рдЧрдПред рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рджреМрдбрд╝ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЗ рдЕрдиреБрд░реВрдк рд╣реЛрдЧрд╛ред

knex QueryBuilder s Promise s рдирд╣реАрдВ рд╣реИрдВ, рд╣рд╛рд▓рд╛рдВрдХрд┐ред рдЬрдм рдЖрдк knex рдХреНрд╡реЗрд░реА рд▓рд┐рдЦрдирд╛ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк "knexland" рдореЗрдВ рдмрдиреЗ рд░рд╣рддреЗ рд╣реИрдВред рдЖрдк рдЬреЛ рдХреБрдЫ рднреА рдХрд░рддреЗ рд╣реИрдВ рд╡рд╣ рдХрдореЛрдмреЗрд╢ рдЙрд╕ рдХреНрд╡реЗрд░реА рдХреЗ JSON рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдирд╛ рд╣реИ рдЬрд┐рд╕реЗ рдЖрдк рдмрдирд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдпрджрд┐ рдЖрдк .toString рдЪрд▓рд╛рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдЗрд╕реЗ рдмрдирд╛рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рдЖрдЙрдЯрдкреБрдЯ рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдПрдХ ( bluebird ) рд╡рд╛рджрд╛ рдирд╣реАрдВ рдмрди рдЬрд╛рддрд╛ рдЬрдм рддрдХ рдХрд┐ рдЖрдк рдЗрдирдореЗрдВ рд╕реЗ рдХрд┐рд╕реА рдПрдХ рдХреЛ рдирд╣реАрдВ рдЪрд▓рд╛рддреЗред рдпрджрд┐ рдЖрдк рдХрдерди рдХреЛ рддреБрд░рдВрдд рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рддреЛ рдЖрдкрдХреЛ .return рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдореЗрдВ рд░реБрдЪрд┐ рд╣реЛ рд╕рдХрддреА рд╣реИред

рдЖрд╣, рдореИрдВ рджреЗрдЦрддрд╛ рд╣реВрдВ, рдЗрд╕рд╕реЗ рдореЗрд░рд╛ рднреНрд░рдо рджреВрд░ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг рдФрд░ рд╕рдВрдХреЗрдд рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж! рдореЗрд░рд╛ рдореБрджреНрджрд╛ рддрдм рдХрд╣реАрдВ рдФрд░ рдореМрдЬреВрдж рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред

рдПрдХ рддрд░рдл, рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣ рддреБрд░рдВрдд рдирд╣реАрдВ рдЪрд▓рддрд╛ рд╣реИ рдЕрдХреНрд╕рд░ рдЙрдкрдпреЛрдЧреА рд╣реЛрддрд╛ рд╣реИред рдХрднреА-рдХрднреА рдЖрдк рдХреНрд░рд┐рдпрд╛рдиреНрд╡рд┐рдд рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдЪреАрдЬрд╝ рдХреЛ рдЗрдзрд░-рдЙрдзрд░ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдЙрд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдирд╛ред рдРрд╕реА рд╕реНрдерд┐рддрд┐рдпрд╛рдВ рднреА рд╣реИрдВ рдЬрд╣рд╛рдВ рдЖрдк рд╕рд╛рдорд╛рди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреИрд╕реЗ ...

const medicalBuildings = knex.select('building_id').from('buildings').where({type: 'medical'})
const medicalWorkers = knex.select().from('workers').whereIn('building', medicalBuildings)

(рд╕реБрдкрд░ рдХрд╛рд▓реНрдкрдирд┐рдХ рдЙрджрд╛рд╣рд░рдг рд▓реЗрдХрд┐рди рдЪрд▓рд┐рдП рдЗрд╕рдХреЗ рд╕рд╛рде рдЪрд▓рддреЗ рд╣реИрдВ)

рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЙрд╕ рдкрд╣рд▓реЗ рдХрдерди рдХреЛ рдирд╣реАрдВ рдЪрд▓рд╛рдирд╛ рдЪрд╛рд╣рддрд╛ - рдпрд╣ рдореЗрд░реЗ рджреВрд╕рд░реЗ рдХрдерди рдХрд╛ рд╕рд┐рд░реНрдл рдПрдХ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИред

рдпрд╣ рдЙрд▓реНрд▓реЗрдЦ рдирд╣реАрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдпрджрд┐ рд╕рднреА рдХреНрд╡реЗрд░реА рдмрд┐рд▓реНрдбрд░реНрд╕ рдирд┐рд░реНрдорд╛рдг рдкрд░ рдЕрдорд▓ рдХрд░реЗрдВрдЧреЗ рддреЛ рдмрд┐рд▓реНрдбрд░ рдкреИрдЯрд░реНрди рдХреНрд╡реЗрд░реА рдмрд┐рд▓реНрдбрд┐рдВрдЧ рд╣реЛрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЯреНрд░рд┐рдЧрд░ рд╣реЛ рдЬрд╛рдПрдЧреАред рдпрд╣ рдХреБрдЫ рдЯрд░реНрдорд┐рдиреЗрдЯрд░ рд╡рд┐рдзрд┐ (рдЬреЛ рдХреНрд╡реЗрд░реА рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддрд╛ рд╣реИ) рдХреЗ рдмрд┐рдирд╛ рдмрд┐рд▓реНрдХреБрд▓ рднреА рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ред

@elhigu рдореЗрд░рд╛ рдорддрд▓рдм рд╣реИ ... рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЖрдк рдЗрд╕реЗ рд╣рдореЗрд╢рд╛ рдЕрдЧрд▓реЗ рдЯрд┐рдХ рдкрд░ рдЪрд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВ, рд╣реИ рдирд╛? рдореИрдВ рдпрд╣ рд╕реБрдЭрд╛рд╡ рдирд╣реАрдВ рджреЗ рд░рд╣рд╛ рд╣реВрдВ рдХрд┐ рдХрд┐рд╕реА рднреА рддрд░рд╣ рд╕реЗ рдпрд╣ рдПрдХ рдЕрдЪреНрдЫрд╛ рд╡рд┐рдЪрд╛рд░ рд╣реЛрдЧрд╛ рд▓реЗрдХрд┐рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХрд┐рддрдиреЗ рдкреНрд░рд╢реНрди рдЕрд▓рдЧ-рдЕрд▓рдЧ рдЯрд┐рдХреЛрдВ рдкрд░ рдмрдирд╛рдП рдФрд░ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ?

@timhuff рдореИрдВрдиреЗ рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд╣реАрдВ рд╕реЛрдЪрд╛ рдерд╛ред рд╣рд╛рдБ, рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рднреА рд╕рдВрднрд╡ рд╣реЛрдЧрд╛ред рдореБрдЭреЗ рдорд╛рдорд▓рд╛ рдХрд╛рдлреА рд╕рд╛рдорд╛рдиреНрдп рд▓рдЧрддрд╛ рд╣реИ рдЬрд╣рд╛рдБ рдХреЛрдИ рдХреНрд╡реЗрд░реА рдмрдирд╛рдирд╛ рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реИ, рдлрд┐рд░ рдХреБрдЫ async рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЕрдзрд┐рдХ рдирд┐рд░реНрдорд╛рдг рдХрд░рддрд╛ рд░рд╣рддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐ рдореИрдВ рдРрд╕рд╛ рдмрд╣реБрдд рдмрд╛рд░ рдирд╣реАрдВ рдХрд░рддрд╛ред

@lukewlms рдХрд┐ 'рдирд┐рд╖реНрдкрд╛рджрд┐рдд ()' -рдЬреИрд╕реА рд╡рд┐рдзрд┐ рдХреЛ '.then ()' рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрдм рдЖрдк рдХреНрд╡реЗрд░реА рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдФрд░ рд╡рд╛рджрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рддреЛ рдЖрдк рдЗрд╕реЗ рд╣рдореЗрд╢рд╛ рдХреЙрд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рдареАрдХ рд╣реИ рдХрд┐ 'рддрдм рдХрд░рдиреЗ рдпреЛрдЧреНрдп' рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рд╡рд╛рджреЗ рдХреА рдХрд▓реНрдкрдирд╛ рдореЗрдВ рд╕рдордЭрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред рд╡рд╛рджреЛрдВ рдФрд░ async/рдкреНрд░рддреАрдХреНрд╖рд╛ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХреЗ рджреМрд░рд╛рди рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдпрд╣ рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдФрд░ рд╡реНрдпрд╛рдкрдХ рд░реВрдк рд╕реЗ рдЙрдкрдпреЛрдЧ рдХреА рдЬрд╛рдиреЗ рд╡рд╛рд▓реА рдЕрд╡рдзрд╛рд░рдгрд╛ рд╣реИ (рдЬреЛ Promise.resolve рдФрд░ .then рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рд╣реА рд╢рд╛рдирджрд╛рд░ рд╢реЙрд░реНрдЯрдХрдЯ рд╣реИрдВ)ред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдпрджрд┐ рдЖрдк рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЛ рд╕рдВрднрд╛рд▓реЗ рдмрд┐рдирд╛ рдкреНрд░рд╢реНрдиреЛрдВ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ рддреЛ рдЖрдк рдРрдк рдХреНрд░реИрд╢ рд╣реЛрдиреЗ рдЬреИрд╕реА рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреА рддрд▓рд╛рд╢ рдХрд░ рд░рд╣реЗ рд╣реИрдВред

рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЗрд╕ рдкреАрдЖрд░ рдХреЛ рдЕрдкреНрд╕рд░реНрдЯ рдлреАрдЪрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкрд╛рд▓рди рдХрд░рдирд╛ рдмреЗрд╣рддрд░ рд╣реИ https://github.com/tgriesser/knex/pull/2197 рдпрд╣ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдкреАрдЖрдИ рдбрд┐рдЬрд╛рдЗрди рдХрд░ рдЪреБрдХрд╛ рд╣реИ рдХрд┐ рдЗрд╕реЗ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЗрд╕ рдзрд╛рдЧреЗ рдореЗрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреЛрдИ рдЙрдкрдпреЛрдЧреА рдЬрд╛рдирдХрд╛рд░реА рдирд╣реАрдВ рд╣реИ рдЬрд┐рд╕рдХрд╛ рдЙрд╕ рдкреАрдЖрд░ рдХреА рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЙрд▓реНрд▓реЗрдЦ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ (рдкреАрдЖрд░ рдмрдВрдж рд╣реИ рдФрд░ рдХрднреА рдкреВрд░рд╛ рдирд╣реАрдВ рд╣реБрдЖ) рдЕрддрд┐рд░рд┐рдХреНрдд рдПрдкреАрдЖрдИ рд╡рд┐рд╡рд░рдг рдХреЗ рд╕рд╛рде рдЗрд╕рдХреЗ рд▓рд┐рдП рдирдпрд╛ рдореБрджреНрджрд╛ рдЦреЛрд▓рдиреЗ рджреЗрддрд╛ рд╣реИред

@elhigu рд╕рд┐рд░ рдКрдкрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж! рдореИрдВ рдЙрд╕ рдзрд╛рдЧреЗ рд╕реЗ рдЕрдирдЬрд╛рди рдерд╛ред рдпрд╣ рдЬрд╛рдирдХрд░ рдЕрдЪреНрдЫрд╛ рд▓рдЧрд╛ рдХрд┐ рд╣рдо рдПрдкреАрдЖрдИ рдореЗрдВ рдЖрдиреЗ рд╡рд╛рд▓реЗ рдЕрдкреНрд╕рд░реНрдЯ рдкрд░ рдкреНрд░рдЧрддрд┐ рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ 6 рдорд╣реАрдиреЗ рдкрд╣рд▓реЗ рдпрд╣ 802 рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ рд╕реЗ 1 рдореЗрдВ рд╡рд┐рдлрд▓ рд░рд╣рд╛ рдерд╛ рдФрд░ рдЗрд╕рд▓рд┐рдП рдпрд╣ рдХрднреА рднреА рдЯреНрд░реИрд╡рд┐рд╕-рд╕реАрдЖрдИ рдкрд╛рд╕ рдирд╣реАрдВ рд╣реБрдЖред рдХреНрдпрд╛ рд╡рд╣ 1 рдлреЗрд▓рд┐рдВрдЧ рдЯреЗрд╕реНрдЯ рдХреЗрд╕ рд╣реА рдЗрд╕реЗ knex API рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рдмрдирдиреЗ рд╕реЗ рд░реЛрдХ рд░рд╣рд╛ рд╣реИ?

@timhuff рдХреЗрд╡рд▓ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЗрд╕реЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЙрд╕ рдкреАрдЖрд░ рдХрд╛ рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣рд┐рд╕реНрд╕рд╛ рд╕рд╛рдорд╛рдиреНрдп рдПрдкреАрдЖрдИ рдбрд┐рдЬрд╝рд╛рдЗрди рд╣реИ, рдЬрд┐рд╕реЗ рдЕрдзрд┐рдХрд╛рдВрд╢ рдмреЛрд▓рд┐рдпреЛрдВ рджреНрд╡рд╛рд░рд╛ рд╕рдорд░реНрдерд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рддреЛ рд╕реБрд╡рд┐рдзрд╛ рддрдм рдЖрддреА рд╣реИ рдЬрдм рдХреЛрдИ рдЙрд╕ рдПрдкреАрдЖрдИ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд░рддрд╛ рд╣реИред рдпрджрд┐ рдХреЛрдИ рдФрд░ рдРрд╕рд╛ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдХрд┐рд╕реА рджрд┐рди рдореЗрд░реЗ рдкрд╛рд╕ рдХреБрдЫ рдЕрддрд┐рд░рд┐рдХреНрдд рд╕рдордп рд╣реИ рдпрд╛ рдЗрд╕рдХреА рдмреБрд░реА рддрд░рд╣ рд╕реЗ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рдореИрдВ рдЗрд╕реЗ рд╕реНрд╡рдпрдВ рдХрд░реВрдБрдЧрд╛ред рдпрд╣ рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╡рд┐рд╢реЗрд╖рддрд╛ рдореЗрдВ рд╕реЗ рдПрдХ рд╣реИ рдЬрд┐рд╕реЗ рдореИрдВ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ (рдЕрдкрдбреЗрдЯ рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реЛрдиреЗ рдХреЗ рдЕрд▓рд╛рд╡рд╛)ред

@elhigu рдореБрдЭреЗ рднрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред рдЬрдм рдореБрдЭреЗ рдереЛрдбрд╝рд╛ рдФрд░ рд╕рдордп рдорд┐рд▓реЗрдЧрд╛ рддреЛ рдореБрдЭреЗ рдпрд╣рд╛рдВ рдкреНрд░рдЧрддрд┐ рдкрд░ рдкрдврд╝рдирд╛ рд╣реЛрдЧрд╛ред

рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рдХрд┐рд╕реА рдХреА рдорджрдж рдХрд░рддрд╛ рд╣реИ рдпрд╛ рдЕрдЧрд░ рдореИрдВ рд╕рд┐рд░реНрдл рдПрдХ рдиреЛрдм рд╣реВрдВ, рд▓реЗрдХрд┐рди @timhuff рдХреЗ рд╕рдорд╛рдзрд╛рди рдХреЗ рд▓рд┐рдП рдореБрдЭреЗ рдЙрджреНрдзрд░рдгреЛрдВ рдореЗрдВ рдЕрдкрдиреА рдмрд╛рдзрд╛ рд▓рдкреЗрдЯрдиреА рдкрдбрд╝реА рдХреНрдпреЛрдВрдХрд┐ рдореБрдЭреЗ рдПрдХ рдХреНрд╡реЗрд░реА рд╕рд┐рдВрдЯреИрдХреНрд╕ рддреНрд░реБрдЯрд┐ рдорд┐рд▓ рд░рд╣реА рдереАред

const contraint = '("a", "b")'

рдореИрдВ рдЗрд╕ рдореБрджреНрджреЗ рдкрд░ рдХрдИ рдмрд╛рд░ рдПрдХ knex- рдЖрдзрд╛рд░рд┐рдд Postgres upsert рдХреА рддрд▓рд╛рд╢ рдореЗрдВ рдЖрдпрд╛ рд╣реВрдБред рдЕрдЧрд░ рдХрд┐рд╕реА рдФрд░ рдХреЛ рдЗрд╕рдХреА рдЬрд╝рд░реВрд░рдд рд╣реИ, рддреЛ рдпрд╣ рдХреИрд╕реЗ рдХрд░рдирд╛ рд╣реИред рдореИрдВрдиреЗ рдЗрд╕реЗ рдПрдХрд▓ рдФрд░ рд╕рдордЧреНрд░ рдЕрджреНрд╡рд┐рддреАрдп рдХреБрдВрдЬреА рджреЛрдиреЛрдВ рдХреЗ рд╡рд┐рд░реБрджреНрдз рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рд╣реИред

рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдирд╛

рдиреАрдЪреЗ рджреА рдЧрдИ рддрд╛рд▓рд┐рдХрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдЕрджреНрд╡рд┐рддреАрдп рдХреБрдВрдЬреА рдмрд╛рдзрд╛ рдмрдирд╛рдПрдВред рдореБрдЭреЗ рдПрдХ рд╕рдордЧреНрд░ рдХреБрдВрдЬреА рдмрд╛рдзрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдереА:

table.unique(['a', 'b'])

рдХрд╛рд░реНрдпрдХреНрд░рдо

(рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ: рдХрдЪреНрдЪреЗ рдкреИрд░рд╛рдореАрдЯрд░ рдмрд╛рдЗрдВрдбрд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрджреНрдпрддрди)

const upsert = (params)=> {
  const {table, object, constraint} = params;
  const insert = knex(table).insert(object);
  const update = knex.queryBuilder().update(object);
  return knex.raw(`? ON CONFLICT ${constraint} DO ? returning *`, [insert, update]).get('rows').get(0);
};

рдкреНрд░рдпреЛрдЧ

const objToUpsert = {a:1, b:2, c:3}

upsert({
  table: 'test',
  object: objToUpsert,
  constraint: '(a, b)',
})

рдпрджрд┐ рдЖрдкрдХреА рдмрд╛рдзрд╛ рд╕рдордЧреНрд░ рдирд╣реАрдВ рд╣реИ, рддреЛ рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ, рд╡рд╣ рдПрдХ рдкрдВрдХреНрддрд┐ рдХреЗрд╡рд▓ constraint: '(a)' рд╣реЛрдЧреАред

рдпрд╣ рдпрд╛ рддреЛ рдЕрджреНрдпрддрди рд╡рд╕реНрддреБ рдпрд╛ рд╕рдореНрдорд┐рд▓рд┐рдд рд╡рд╕реНрддреБ рд▓реМрдЯрд╛рдПрдЧрд╛ред

рд╕рдордЧреНрд░ рдЕрд╢рдХреНрдд рд╕реВрдЪрдХрд╛рдВрдХреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рдиреЛрдЯ

рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдПрдХ рд╕рдордЧреНрд░ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рд╣реИ (a,b) рдФрд░ b рдЕрд╢рдХреНрдд рд╣реИ, рддреЛ рдореВрд▓реНрдпреЛрдВ (1, NULL) рдФрд░ (1, NULL) рдХреЛ Postgres рджреНрд╡рд╛рд░рд╛ рдкрд╛рд░рд╕реНрдкрд░рд┐рдХ рд░реВрдк рд╕реЗ рдЕрджреНрд╡рд┐рддреАрдп рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ (рдореБрдЭреЗ рдпрд╣ рдирд╣реАрдВ рдорд┐рд▓рд╛ рджреЛрдиреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ)ред рдпрджрд┐ рдпрд╣ рдЖрдкрдХрд╛ рдЙрдкрдпреЛрдЧ рдорд╛рдорд▓рд╛ рд╣реИ, рддреЛ рдЖрдкрдХреЛ рдЖрдВрд╢рд┐рдХ рдЕрджреНрд╡рд┐рддреАрдп рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА рдФрд░ рдлрд┐рд░ рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдХрд┐рд╕ рдмрд╛рдзрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ, рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкреНрд╕рд░реНрдЯ рд╕реЗ рдкрд╣рд▓реЗ рд╢реВрдиреНрдп рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг рдХрд░реЗрдВред рдЖрдВрд╢рд┐рдХ рдЕрджреНрд╡рд┐рддреАрдп рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдмрдирд╛рдиреЗ рдХрд╛ рддрд░реАрдХрд╛ рдпрд╣рд╛рдВ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ: CREATE UNIQUE INDEX unique_index_name ON table (a) WHERE b IS NULL ред рдпрджрд┐ рдЖрдкрдХрд╛ рдкрд░реАрдХреНрд╖рдг рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ b рд╢реВрдиреНрдп рд╣реИ, рддреЛ рдЖрдкрдХреЛ рдЗрд╕ рдмрд╛рдзрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЕрдкрдиреЗ рдЕрдкреНрд╕рд░реНрдЯ рдореЗрдВ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА: constraint: '(a) WHERE b IS NULL' ред рдпрджрд┐ a рднреА рд╢реВрдиреНрдп рд╣реИ, рддреЛ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЖрдкрдХреЛ 3 рдЕрджреНрд╡рд┐рддреАрдп рд╕реВрдЪрдХрд╛рдВрдХ рдФрд░ 4 if/else рд╢рд╛рдЦрд╛рдУрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА (рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рдореЗрд░рд╛ рдЙрдкрдпреЛрдЧ рдорд╛рдорд▓рд╛ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ)ред

рдпрд╣рд╛рдБ рд╕рдВрдХрд▓рд┐рдд рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╣реИ ред

рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдХрд┐рд╕реА рдХреЛ рдпрд╣ рдЙрдкрдпреЛрдЧреА рд▓рдЧреЗрдЧрд╛ред @elhigu ~ knex().update(object) рдХреЗ рдЙрдкрдпреЛрдЧ рдкрд░ рдХреЛрдИ рдЯрд┐рдкреНрдкрдгреА?~ (рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ: рдХреЛрдИ рдмрд╛рдд рдирд╣реАрдВ - рдЪреЗрддрд╛рд╡рдиреА рджреЗрдЦреА - рдЕрдм knex.queryBuilder() рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ)

рдХреБрдЫ рдЕрд╕рдВрдмрдВрдзрд┐рдд рдЪрд░реНрдЪрд╛рдУрдВ рдХреЛ рд╣рдЯрд╛ рджрд┐рдпрд╛ (рд╡рд╛рджреЛрдВ/рдлрд┐рд░ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ) рдХреЗ рдмрд╛рд░реЗ рдореЗрдВред

рдХреНрдпрд╛ рдпрд╣ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛?

рдирд╣реАрдВред https://github.com/knex/knex/issues/3186 . рдореЗрдВ рд╕реБрд╡рд┐рдзрд╛ рдЕрдиреБрд░реЛрдз рдФрд░ рд╡рд┐рд╢рд┐рд╖реНрдЯрддрд╛ рд╣реИ

рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕