@adamscybotã«ãã£ãŠtgriesser / bookshelfïŒ55ã§åãäžããããŸãããããã¯ãè¿œå ããã®ã«é©ããæ©èœã§ããå¯èœæ§ããããŸãã
ç§ã¯åæããŸããããã¯çŽ æŽãããæ©èœã«ãªãã§ãããïŒ
ïŒ+1ïŒ
ïŒ+1ïŒ
CSVããããã€ãã®ããŒã¿ãã€ã³ããŒãããŠããŸãããããã€ãã®ã¬ã³ãŒããååã®ã€ã³ããŒããšéè€ããŠããå¯èœæ§ããããŸãïŒã€ãŸããååã¯1æ1æ¥ãã5æ31æ¥ãŸã§ã€ã³ããŒããããä»åã¯5æ31æ¥ãã6æ18æ¥ãŸã§ã€ã³ããŒããããŸããïŒã
幞ãããµãŒãããŒãã£ã®ã·ã¹ãã ã¯ç¢ºå®ã«äžæã®IDãå²ãåœãŠãŸãã
æ°ããã¬ã³ãŒããæ¿å ¥ããŠå€ãã¬ã³ãŒããæŽæ°ããããã®æè¯ã®æ¹æ³ã¯äœã§ããïŒ
ãŸã è©ŠããŠããŸãããããããªæãã«ãªããšæã£ãŠããŸããã
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');
});
});
ãŸããç§ãä¿åããŠãããã®ã¯ãããã·ã¥ãªã©ã®ç¢ºå®ããidå€ã«ãã£ãŠä¿åãããããšããããŸãã ãã®ãããªå Žåã¯ãããŒã¿ãè¿œå ãŸãã¯çœ®æãããã ãã§ãã
ç§ã¯ãã€ãSQLãåŸæ¥ã®SQLãšããŠäœ¿çšããŠããããã§ã¯ãããŸããã å€ãã®å Žåãæ確ãªé¢ä¿ãããã³ã°ãšã€ã³ããã¯ã¹ã®å©ç¹ãåãããã€ããªããNoSQLãšããŠäœ¿çšããŸãã
ïŒ+1ïŒ
ããã«ã¡ã¯ã
ãã®æ°æ©èœã«ã€ããŠã®ãã¥ãŒã¹ã¯ãããŸããïŒ
ãŸãã¯ã誰ããmysqlã®ãã®æ©èœãã·ãã¥ã¬ãŒãããæ¹æ³ã瀺ãäŸãæšå¥šã§ããŸããïŒ
ã©ãã
çŸåšãç§ã¯raw
ã§ãããè¡ã£ãŠããŸããããããããã«ããã§å©çšã§ããããã«ããããã«äžçæžåœåãçµãã§ããŸãã
ã¡ãªã¿ã«ãPostgresã¯ã¢ãããµãŒããµããŒããå®è£ ããŸããïŒ+1ïŒ
https://news.ycombinator.com/item?id=9509870
æ§æã¯INSERT ... ON CONFLICT DO UPDATE
ã§ã
MySqlã§REPLACE INTO
ãå®è¡ããæ¹æ³ãæ¢ããŠãããšããããã®æ©èœãªã¯ãšã¹ããèŠã€ãããŸããã REPLACE
ãšINSERT
ã¯MySqlã§ãŸã£ããåãæ§æãæã£ãŠããã®ã§ã ON DUPLICATE KEY UPDATE
ãããå®è£
ãç°¡åã ãšæããŸãã REPLACE
ãå®è£
ããèšç»ã¯ãããŸããïŒ PRã¯äŸ¡å€ã®ãããã®ã§ããããïŒ
ç¹ã«PostreSQL9.5ã§ãããã«é¢ããæŽæ°ã¯ãããŸããïŒ
éèŠãªè³ªåã®1ã€ã¯ãPostgreSQLãMySQLãªã©ã®ããŸããŸãªæ¹èšã«åãupsert
ã¡ãœããã·ã°ããã£ãå
¬éãããã©ããã§ãã Sequelizeã§ã upsert
ã®æ»ãå€ã«é¢ããåé¡ãçºçããŸããïŒ httpsïŒ//github.com/sequelize/sequelize/issues/3354ã
äžéšã®KnexJSã©ã€ãã©ãªã¡ãœããã«ã¯ãããŸããŸãªæ¹èšã®ã³ã³ããã¹ãã§ã®æ»ãå€ã«é¢ããéããããããšã«æ°ä»ããŸããïŒ insert
ãªã©ãæåã«æ¿å
¥ãããIDã®é
åãSqliteãšMySQLã«å¯ŸããŠè¿ããããã¹ãŠã®é
åãè¿ãããæ¿å
¥ãããIDã¯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
ã«ãŠã³ãã¯ãæ¿å ¥ãŸãã¯æŽæ°ãããè¡ã®æ°ã§ãã countãæ£ç¢ºã«1ã§ãããã¿ãŒã²ããããŒãã«ã«OIDãããå Žåãoidã¯æ¿å ¥ãããè¡ã«å²ãåœãŠãããOIDã§ãã åäžã®è¡ã¯ãæŽæ°ãããã®ã§ã¯ãªãæ¿å ¥ãããŠããå¿ èŠããããŸãã ãã以å€ã®å Žåãoidã¯ãŒãã§ãã
INSERTã³ãã³ãã«RETURNINGå¥ãå«ãŸããŠããå Žåãçµæã¯ãã³ãã³ãã«ãã£ãŠæ¿å ¥ãŸãã¯æŽæ°ãããè¡ã«å¯ŸããŠèšç®ããããRETURNINGãªã¹ãã§å®çŸ©ãããåãšå€ãå«ãSELECTã¹ããŒãã¡ã³ãã®çµæãšåæ§ã«ãªããŸãã
ãã®å Žåãæ»ãå€ã¯RETURNING
å¥ã§å€æŽã§ããŸãã
èãïŒ
Client_PGã«ã¢ã³ããŒããããé©çšããŠãæ¿å ¥çšã®ãonConflictãã¡ãœãããè¿œå ããŸããã github oauthã¯ã¬ãã³ã·ã£ã«ãã¢ãããµãŒãããããšãããšã次ã®ããã«ã¯ãšãªãèšè¿°ã§ããŸãã
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
æ¢ç¥ã®åé¡ïŒ
count = count + 1
ã®ãããªçã®æŽæ°ããµããŒãããŠããŸãããã£ãŒãããã¯ïŒ
@hayeahç§ã¯ããªãã®ã¢ãããŒãã奜ãã§ãPostgresã«é©ããŠããŸãã ãããžã§ã¯ãã§ããªãã®ã¢ã³ããŒããããè©ŠããŠãããªããææããåé¡ä»¥å€ã®åé¡ãçµéšçã«æ€åºã§ãããã©ããã確èªããŸãã
æ§æã®ææ¡ïŒ knex('table').upsert(['col1','col2']).insert({...}).update({...});
ããã§ã upsert
ã¯æ¡ä»¶ã¹ããŒãã¡ã³ããåããŸãã ãã®ããã«ãdbåºæã§ã¯ãããŸããã
ã¢ãããµãŒãã®ããŸããŸãªå®è£ ã®æŠèŠã¯ã httpsïŒ//en.wikipedia.org/wiki/Merge_ ïŒSQLïŒã«ãããŸãã
ç§ããã®æ©èœã«èå³ããããŸãã ãŠãŒã¹ã±ãŒã¹ïŒå€éšãµãŒãã¹ããã®å€§éã®å€éšããŒã¿ã«äŸåããã·ã¹ãã ãæ§ç¯ããŸãã ããŒã«ã«ã®MySQLããŒã¿ããŒã¹ã«ä¿åããããŒã¿ãå®æçã«ããŒãªã³ã°ããŸãã ããããä»ã®ãšããknex.rawã䜿çšããŠããã§ãããã
ãŸãèå³ããããŸãããç§ã®ãŠãŒã¹ã±ãŒã¹ã§ã¯ãåã«åžžã«ãäžæã®ãå¶çŽããããšã¯éããªãããã競åã«åºã¥ããªãæ¹æ³ã§æ©èœãããå¿ èŠããããŸã-ååšããå Žåã¯ã¯ãšãªã«äžèŽãããšã³ããªãæŽæ°ããã ãã§ããããã§ãªãå Žåã¯æ¿å ¥ããŸãæ°ããè¡ã
@haywirezãªãç¬èªã®å¶çŽããªãã®ãç¥ãããã®ã§ããïŒ ç«¶åç¶æ ã«ãããããŸãããïŒ
@hayeahç¹å®ã®æ¥ã«é¢é£ä»ããããå€ãæã€ãšã³ããªãæ ŒçŽãããæéæ ä»ãã®ããŒã¿ã䜿çšããç¹å®ã®ãŠãŒã¹ã±ãŒã¹ããããŸãã ãããã£ãŠãäžèŽããïŒæ¥ïŒã¿ã€ã ã¹ã¿ã³ãã®ãçµåããŒããšãä»ã®ããŒãã«ã®PKã«å¯Ÿå¿ããä»ã®2ã€ã®IDãæã€ãšã³ããªãæ¿å ¥ããã³æŽæ°ããŠããŸãã 24æé以å ã«ãããããæ¿å ¥ããããææ°ã®ã«ãŠã³ãã§æŽæ°ããå¿ èŠããããŸãã
ããã¯çŽ æŽãããæ©èœã§ãïŒ
ããã«ã¡ã¯ãããã«ã³ã¡ã³ãããããšã®ããçããã PRãé¡ãã©ãã«ãè¿œå ããŸãã
ãã®æ©èœãè¿œå ããPRãåãã§åããŸãããæåã«ããã§ç®çã®APIã®èª¬æãèŠãŠã¿ãããšæããŸãã
PSã
^åæããŸããã
ãã®ãããªã³ã¡ã³ããåé€ããŸãã+ 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æäŸããMongoDBã®äŸã§ã¯ããæåã«UPDATE WHERE ...ãè©Šè¡ããã¯ãšãªã«äžèŽããããã¥ã¡ã³ãããªãå Žåã¯INSERTãå®è¡ããŸãããšè¡šç€ºãããŸãããSQLUPSERTã§ã¯ãINSERTINTO ... UPDATINGïŒãã®äž»ããŒã®è¡ãæ¢ã«ååšããå ŽåïŒããšè¡šç€ºãããŸãã ã
ã€ãŸããSQLããŒã¿ããŒã¹ã«å®è£
ãããŠãããã®ãšã¯ãŸã£ããç°ãªããã¢ãããµãŒããã«ã€ããŠè©±ããŠãããšæããŸãã
ç§ã¯ãã®APIãææ¡ããŸãïŒ
knex.createTable('test')
.bigserial('id')
.varchar('unique').notNull().unique()
.varchar('whatever')
knex.table('test').insert(object, { upsert: ['unique'] })
.insert()
é¢æ°ã¯ã2çªç®ã®ãã©ã¡ãŒã¿ãŒãåæããŸãã
æååã®å Žåã¯ãå€ãreturning
ãã©ã¡ãŒã¿ã§ãã
ãªããžã§ã¯ãã®å Žåã¯ã options.returning
ãšoptions.upsert
ãæã€$ options
ãã©ã¡ãŒã¿ã§ããããã§ã options.upsert
ã¯äžæããŒã®ãªã¹ãã§ãïŒ1ãè¶
ããå ŽåããããŸãïŒãè€åäžæããŒå¶çŽã®å ŽåïŒã
次ã«ãSQLã¯ãšãªãçæãããŸãããã®ã¯ãšãªã¯ãäž»ããŒãšãã¹ãŠã®options.upsert
ããŒãobject
ããïŒ clone(object) && delete cloned_object.id && delete cloned_object.unique
çµç±ã§ïŒé€å€ãããã®cloned_object
ã䜿çšããŠåé€ããŸãã SQLã¯ãšãªã®2çªç®ã®éšåã§ããSET
å¥ãæ§æããããã®äž»ããŒïŒããã³äžæã®ããŒïŒïŒ ... ON CONFLICT DO UPDATE SET [iterate cloned_object]
ã
ããã¯ãçŸåšã®APIãšåçš®ã®æãåçŽã§æ確ãªãœãªã¥ãŒã·ã§ã³ã«ãªããšæããŸãã
@slavafomin @ScionOfBytesAPIã§ãããŸã åæãããŠããªãããã§ãã ããã次ã®ã¹ãããã§ããããããå®è£ ããã®ã奜ããªäººã¯ãããããããããŸããã ã ãããã¥ãŒã¹ã¯ãããŸããã
psã ãã®ã¹ã¬ããããã¥ãŒã¹ãªã¯ãšã¹ãã¹ãã ããã®ä»ã®é¢é£æ§ã®äœãã¡ãã»ãŒãžã§ãã£ã±ãã«ãªãã®ãé²ãããã®ãªã¯ãšã¹ãããªãå Žåã¯ãè¿œå ã®ãã¥ãŒã¹ãªã¯ãšã¹ããåé€ãå§ããŸããã
@ amir-såæããŸããããã®åé¡ã®äž»é¡ã¯ã¢ãããµãŒãæ©èœã§ãã
IMOãæ¬åœã®åé¡ã¯APIã§ã¯ãªããåããŒã¿ããŒã¹ã§ã¢ãããµãŒããè¡ãçããæ¹æ³ã§ãã
MySQLïŒON DUPLICATE KEY UPDATEïŒããã³PostgreSQL 9.5+ïŒON CONFLICT DO UPDATEïŒã¯ãããã©ã«ãã§ã¢ãããµãŒãããµããŒãããŸãã
MSSQLãšOracleã¯mergeå¥ã§ããããµããŒãã§ããŸãããknexã¯ã¯ãšãªãäœæã§ããããã«ã競åããåã®ååãç¥ã£ãŠããå¿ èŠããããŸãã
-- 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ã¯ããã§ã¯ãããŸããã§ããã ã¢ãããµãŒããã·ãã¥ã¬ãŒãããã«ã¯ã2ã€ã®ã¯ãšãªãå¿ èŠã§ã
-- '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))
CTEã䜿çšããå¥ã®ãœãªã¥ãŒã·ã§ã³ããã®ã¹ã¿ãã¯ãªãŒããŒãããŒã®åçãèŠãŠãã ãã
ç§ã¯ãknexããŒã¹ã®Postgresã¢ãããµãŒããæ¢ããŠãã®åé¡ã«äœåºŠãééããŸããã ä»ã®èª°ãããããå¿ èŠãšããå Žåããããè¡ãæ¹æ³ã¯æ¬¡ã®ãšããã§ãã ãããåäžããã³è€åã®äžæããŒã®äž¡æ¹ã«å¯ŸããŠãã¹ãããŸããã
以äžã䜿çšããŠãããŒãã«ã«äžæã®ããŒå¶çŽãäœæããŸãã è€åããŒå¶çŽãå¿ èŠã§ããïŒ
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)',
})
å¶çŽãåæã§ãªãå Žåãåœç¶ããã®1è¡ã¯constraint: '(a)'
ã«ãªããŸãã
ããã«ãããæŽæ°ããããªããžã§ã¯ããŸãã¯æ¿å ¥ããããªããžã§ã¯ãã®ãããããè¿ãããŸãã
è€ånull蚱容ã€ã³ããã¯ã¹ã«é¢ãã泚æ
è€åã€ã³ããã¯ã¹
(a,b)
ããããb
ãnull蚱容ã§ããå Žåãå€(1, NULL)
ãš(1, NULL)
ã¯Postgresã«ãã£ãŠçžäºã«äžæã§ãããšèŠãªãããŸãïŒããããŸããïŒãŸãïŒã ããããŠãŒã¹ã±ãŒã¹ã§ããå Žåã¯ãéšåçã«äžæã®ã€ã³ããã¯ã¹ãäœæããã¢ãããµãŒãããåã«nullããã¹ãããŠã䜿çšããå¶çŽã決å®ããå¿ èŠããããŸãã éšåçã«äžæã®ã€ã³ããã¯ã¹ãäœæããæ¹æ³ã¯æ¬¡ã®ãšããã§ãïŒCREATE UNIQUE INDEX unique_index_name ON table (a) WHERE b IS NULL
ã ãã¹ãã§b
ãnullã§ãããšå€æãããå Žåã¯ãã¢ãããµãŒãã§æ¬¡ã®å¶çŽã䜿çšããå¿ èŠããããŸãïŒconstraint: '(a) WHERE b IS NULL'
ãa
ãnull蚱容ã®å Žåã3ã€ã®äžæã®ã€ã³ããã¯ã¹ãš4ã€ã®if/else
ãã©ã³ããå¿ èŠã«ãªããšæããŸãïŒããã¯ç§ã®ãŠãŒã¹ã±ãŒã¹ã§ã¯ãªããããããããŸããïŒã
ãããã³ã³ãã€ã«ãããjavascriptã§ãã
誰ããããã圹ã«ç«ã€ãšæãããšãé¡ã£ãŠããŸãã @elhigu ïŒç·šéïŒãããŒãã€ã³ã-èŠåãèŠã-ä»knex().update(object)
ã®äœ¿çšæ³ã«ã€ããŠã³ã¡ã³ãã¯ãããŸããïŒknex.queryBuilder()
ã䜿çšïŒ
@timhuffã¯èŠæ ãããããå€æŽãã1ã€ã®ããšã¯ãå€ã®ãã€ã³ãã䜿çšããŠãåã¯ãšãªãrawã«æž¡ãããšã§ãã ãã以å€ã®å Žåquery.toString()
ã¯ã¯ãšãªã®åéšåãã¬ã³ããªã³ã°ããããã«äœ¿çšãããäŸåæ§æ³šå
¥ã®å¯èœæ§ã®ããç©ŽãéããŸãïŒqueryBuilder.toStringïŒïŒã¯ããã€ã³ãã£ã³ã°ã»ã©ãã©ã€ããŒã«ãã©ã¡ãŒã¿ãŒãæž¡ãã»ã©å®å
šã§ã¯ãããŸããïŒã
@elhiguåŸ
ã£ãŠ... query.toString()
ã¯ãã€ã³ãã£ã³ã°ã䜿çšããŸãããïŒ ããªããæšå¥šããŠããä¿®æ£ã®å€§ãŸããªäŸãæããŠãã ããã ç§ã¯...æŽæ°ããã³ãŒãããããããããããããŸããã
Rawãã€ã³ãã£ã³ã°ãšããã©ãã«ã®ä»ããããã¥ã¡ã³ãã®äžéšãèŠã€ãããŸããã ä»ããæŽæ°äŸãæŽæ°ããŸããã 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ïŒïŒã¯äœ¿çšããªãã§ãã ãããå€ãã®çš®é¡ã®åé¡ãçºçããå¯èœæ§ããããDBãžã®ãã€ã³ãã£ã³ã°ãä»ããŠå€ãæž¡ãããŸããïŒæœåšçãªSQLã€ã³ãžã§ã¯ã·ã§ã³ã®ã»ãã¥ãªãã£ããŒã«ïŒã
ãããé©åã«è¡ãããã®ãšåãããã«ãªããŸãïŒ
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ããããšãTimãç§ã¯ããããã®ãããªãã®ã§ãªããã°ãªããªããšæããŸããããããããã¯çŽæã®ããã®éåžžã®æ¯ãèãã§ã¯ãããŸããã çŽæã¯éåžžãäœææã«å®è¡ãããŸãã ç§ãå°ããçç±ã¯ããã®ã¢ãããµãŒããå®è¡ããããšãããšããæ¥ç¶ãçµäºããŸããããšãããšã©ãŒãé »ç¹ã«çºçããããã§ãã æ¿å ¥ãåé€ããŠå®å šã«çã®ã¯ãšãªãäœæããããã«åãæ¿ãããšããããã¯ãªããªããŸããã ããã¯ç«¶åç¶æ ãšäžèŽããŠããããã§ãã
ãã ããknex QueryBuilder
ã¯Promise
ã§ã¯ãããŸããã knexã¯ãšãªãæžãå§ãããšããknexlandãã«ãšã©ãŸããŸãã äœæããã¯ãšãªã®JSONä»æ§ãæ§æããã ãã§ãå€ããå°ãªããå®è¡ã§ããŸãã .toString
ãå®è¡ãããšããã«ãããŠåºåããŸãã ãããã®ãããããå®è¡ãããŸã§ãïŒ bluebird
ïŒPromiseã«ã¯ãªããŸããã ã¹ããŒãã¡ã³ããããã«å®è¡ãããå Žåã¯ã .return
ã䜿çšããããšããå§ãããŸãã
ããããªãã»ã©ãããã§ç§ã®æ··ä¹±ã¯è§£æ¶ãããŸãã 説æãšãã€ã³ã¿ãããããšãïŒ ç§ã®åé¡ã¯ãã®æä»ã®å Žæã«ååšããŠããã«éããããŸããã
äœè«ã§ãããããã«ã¯å®è¡ãããªããšããäºå®ã¯ãå€ãã®å Žå䟿å©ã§ãã å®è¡ããåã«ãèšå®ããŠãç©ãæž¡ãããå ŽåããããŸãã 次ã®ãããªããšãã§ããç¶æ³ããããŸã...
const medicalBuildings = knex.select('building_id').from('buildings').where({type: 'medical'})
const medicalWorkers = knex.select().from('workers').whereIn('building', medicalBuildings)
ïŒéåžžã«å·¥å€«ãããäŸã§ãããããã䜿ã£ãŠå®è¡ããŸãããïŒ
ç§ã¯å®éã«ã¯ãã®æåã®ã¹ããŒãã¡ã³ããå®è¡ããããããŸãã-ããã¯ç§ã®2çªç®ã®ã¹ããŒãã¡ã³ãã®äžéšã«ãããŸããã
èšããŸã§ããªãããã¹ãŠã®ã¯ãšãªãã«ããŒãäœææã«å®è¡ãããå Žåããã«ããå®äºããåã«ãã«ããŒãã¿ãŒã³ã¯ãšãªãããªã¬ãŒãããŸãã ïŒã¯ãšãªãå®è¡ããïŒã¿ãŒãããŒã¿ã¡ãœããããªããšããŸã£ããæ©èœããŸããã
@elhiguã€ãŸã...次ã®ãã£ãã¯ã§ãã€ã§ãå®è¡ã§ãããšæããŸãããïŒ ç§ã¯ããã決ããŠè¯ãèãã§ããããšã瀺åããŠããŸããããå®éã«ããã€ã®ã¯ãšãªãäœæãããç°ãªããã£ãã¯ã§å®è¡ãããŸããïŒ
@timhuffç§ã¯ããã«ã€ããŠèããŠããŸããã§ããã ããããããå¯èœã ãšæããŸãã ã¯ãšãªã®äœæãéå§ããŠãããéåæããŒã¿ãååŸããŠããã«äœæãç¶ãããšããã±ãŒã¹ã¯éåžžã«äžè¬çã§ãã ã§ããããªããšã¯ããŸãããŸããã
@lukewlmsãã® 'executeïŒïŒ'ã®ãããªã¡ãœãã㯠'.thenïŒïŒ'ãšåŒã°ããã¯ãšãªãå®è¡ããŠpromiseãååŸããããšãã«ãã€ã§ãåŒã³åºãããšãã§ããŸãã ããã¯ãthenableããã©ã®ããã«æ©èœãããã§ãããpromiseä»æ§ã§èª¬æãããŠããŸãã ããã¯ãpromiseãšasync / awaitïŒPromise.resolveãš.thenã®æ å ã®ã·ã§ãŒãã«ããïŒãåŠçãããšãã«javascriptã§åºã䜿çšãããŠããéèŠãªæŠå¿µã®1ã€ã§ãã ãŸããçµæãåŠçããã«ã¯ãšãªãå®è¡ããŠããå Žåã¯ãã¢ããªã®ã¯ã©ãã·ã¥ãªã©ã®åé¡ãæ¢ããŠããŸãã
å®éã«ã¯ãã¢ãããµãŒãæ©èœã®å®è£ ã«ã€ããŠãã®PRã«åŸãã»ããããã§ããããhttpsïŒ//github.com/tgriesser/knex/pull/2197ãã§ã«APIãã©ã®ããã«æ©èœããããèšèšããŠããŸãã ãã®ã¹ã¬ããã«ã¯ããã®PRã®ã³ã¡ã³ãã§ãŸã èšåãããŠããªãæçšãªæ å ±ã¯å®éã«ã¯ãããŸããã å¿ èŠã«å¿ããŠïŒPRã¯éããããå®äºããŸããïŒãè¿œå ã®APIã®èª¬æã䜿çšããŠãã®åé¡ã®æ°ããåé¡ãéãããšãã§ããŸãã
@elhigué ãäžããŠãããŠããããšãïŒ ç§ã¯ãã®ã¹ã¬ããã«æ°ã¥ããŠããŸããã§ããã APIã®ã¢ãããµãŒããé²ãã§ãããšèããŠããããã§ãã 6ãæåã¯ã802ãã¹ãã®1ã€ã«å€±æãããããtravis-ciã«åæ Œããªãã£ãããã§ãã ãã®1ã€ã®å€±æãããã¹ãã±ãŒã¹ã¯ããããknex APIã®äžéšã«ãªãã®ã劚ããå¯äžã®ããšã§ããïŒ
@timhuffã¯æåã®å®è£ ã®ã¿ãè¡ããããããå®å šã«æžãçŽãå¿ èŠããããŸãã ãã®PRã®æãéèŠãªéšåã¯ãã»ãšãã©ã®æ¹èšã§ãµããŒãã§ããå ±éã®APIèšèšã§ãã ãããã£ãŠããã®æ©èœã¯ã誰ãããã®APIãå®è£ ããããšã決å®ãããšãã«æäŸãããŸãã 誰ããããããŠããªããŠããã€ãç§ãäœåãªæéããããããããã²ã©ãå¿ èŠãšããŠãããªããç§ã¯ãããèªåã§ããŸãã ããã¯ãïŒæŽæ°ãžã®çµåã«å ããŠïŒknexã«ååŸããŠãããããæãéèŠãªæ©èœã®1ã€ã§ãã
@elhiguèšå ¥ããŠããã ãããããšãããããŸããããå°ãæéãã§ããããããã§é²æç¶æ³ã確èªããå¿ èŠããããŸãã
ããã誰ãã«åœ¹ç«ã€ã®ãããããšãç§ãåå¿è ãªã®ãã¯ããããŸãããã @ timhuffã®è§£æ±ºçã§ã¯ãã¯ãšãªæ§æãšã©ãŒãçºçãããããå¶çŽãåŒçšç¬Šã§å²ãå¿ èŠããããŸããã
const contraint = '("a", "b")'
ç§ã¯ãknexããŒã¹ã®Postgresã¢ãããµãŒããæ¢ããŠãã®åé¡ã«äœåºŠãééããŸããã ä»ã®èª°ãããããå¿ èŠãšããå Žåããããè¡ãæ¹æ³ã¯æ¬¡ã®ãšããã§ãã ãããåäžããã³è€åã®äžæããŒã®äž¡æ¹ã«å¯ŸããŠãã¹ãããŸããã
ã»ããã¢ãã
以äžã䜿çšããŠãããŒãã«ã«äžæã®ããŒå¶çŽãäœæããŸãã è€åããŒå¶çŽãå¿ èŠã§ããïŒ
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)', })
å¶çŽãåæã§ãªãå Žåãåœç¶ããã®1è¡ã¯
constraint: '(a)'
ã«ãªããŸããããã«ãããæŽæ°ããããªããžã§ã¯ããŸãã¯æ¿å ¥ããããªããžã§ã¯ãã®ãããããè¿ãããŸãã
è€ånull蚱容ã€ã³ããã¯ã¹ã«é¢ãã泚æ
è€åã€ã³ããã¯ã¹
(a,b)
ããããb
ãnull蚱容ã§ããå Žåãå€(1, NULL)
ãš(1, NULL)
ã¯Postgresã«ãã£ãŠçžäºã«äžæã§ãããšèŠãªãããŸãïŒããããŸããïŒãŸãïŒã ããããŠãŒã¹ã±ãŒã¹ã§ããå Žåã¯ãéšåçã«äžæã®ã€ã³ããã¯ã¹ãäœæããã¢ãããµãŒãããåã«nullããã¹ãããŠã䜿çšããå¶çŽã決å®ããå¿ èŠããããŸãã éšåçã«äžæã®ã€ã³ããã¯ã¹ãäœæããæ¹æ³ã¯æ¬¡ã®ãšããã§ãïŒCREATE UNIQUE INDEX unique_index_name ON table (a) WHERE b IS NULL
ã ãã¹ãã§b
ãnullã§ãããšå€æãããå Žåã¯ãã¢ãããµãŒãã§æ¬¡ã®å¶çŽã䜿çšããå¿ èŠããããŸãïŒconstraint: '(a) WHERE b IS NULL'
ãa
ãnull蚱容ã®å Žåã3ã€ã®äžæã®ã€ã³ããã¯ã¹ãš4ã€ã®if/else
ãã©ã³ããå¿ èŠã«ãªããšæããŸãïŒããã¯ç§ã®ãŠãŒã¹ã±ãŒã¹ã§ã¯ãªããããããããŸããïŒããããã³ã³ãã€ã«ãããjavascriptã§ãã
誰ããããã圹ã«ç«ã€ãšæãããšãé¡ã£ãŠããŸãã @ elhiguã
knex().update(object)
ã®äœ¿çšæ³ã«é¢ããã³ã¡ã³ãïŒãïŒç·šéïŒnevermind-èŠåãèŠã-ä»ããknex.queryBuilder()
ã䜿çšïŒ
ããã€ãã®ç¡é¢ä¿ãªè°è«ãåé€ããŸããïŒpromise / thenablesãã©ã®ããã«æ©èœãããã«ã€ããŠïŒã
ããã¯è¿œå ãããŸãããïŒ
ããããhttpsïŒ//github.com/knex/knex/issues/3186ã«æ©èœã®ãªã¯ãšã¹ããšä»æ§ããããŸã
æãåèã«ãªãã³ã¡ã³ã
@NicolajKN toStringïŒïŒã¯äœ¿çšããªãã§ãã ãããå€ãã®çš®é¡ã®åé¡ãçºçããå¯èœæ§ããããDBãžã®ãã€ã³ãã£ã³ã°ãä»ããŠå€ãæž¡ãããŸããïŒæœåšçãªSQLã€ã³ãžã§ã¯ã·ã§ã³ã®ã»ãã¥ãªãã£ããŒã«ïŒã
ãããé©åã«è¡ãããã®ãšåãããã«ãªããŸãïŒ