Normalized database. Updated seed files. Simplified seed upsert.
This commit is contained in:
parent
9b17add4e2
commit
31aee71edb
|
@ -17,6 +17,184 @@ exports.up = knex => Promise.resolve()
|
|||
table.integer('priority', 2)
|
||||
.defaultTo(0);
|
||||
}))
|
||||
.then(() => knex.schema.createTable('media', (table) => {
|
||||
table.increments('id', 16);
|
||||
|
||||
table.string('path');
|
||||
table.string('thumbnail');
|
||||
table.integer('index');
|
||||
table.string('mime');
|
||||
|
||||
table.string('type');
|
||||
table.string('quality', 6);
|
||||
|
||||
table.string('hash');
|
||||
table.text('comment');
|
||||
table.string('source', 1000);
|
||||
|
||||
table.unique('hash');
|
||||
table.unique('source');
|
||||
|
||||
table.datetime('created_at')
|
||||
.defaultTo(knex.fn.now());
|
||||
}))
|
||||
.then(() => knex.schema.createTable('tags_groups', (table) => {
|
||||
table.increments('id', 12);
|
||||
|
||||
table.string('name', 32);
|
||||
table.text('description');
|
||||
|
||||
table.string('slug', 32)
|
||||
.unique();
|
||||
|
||||
table.datetime('created_at')
|
||||
.defaultTo(knex.fn.now());
|
||||
}))
|
||||
.then(() => knex.schema.createTable('tags', (table) => {
|
||||
table.increments('id', 12);
|
||||
table.string('name');
|
||||
|
||||
table.text('description');
|
||||
|
||||
table.integer('priority', 2)
|
||||
.defaultTo(0);
|
||||
|
||||
table.integer('group_id', 12)
|
||||
.references('id')
|
||||
.inTable('tags_groups');
|
||||
|
||||
table.integer('alias_for', 12)
|
||||
.references('id')
|
||||
.inTable('tags');
|
||||
|
||||
table.string('slug', 32)
|
||||
.unique();
|
||||
|
||||
table.datetime('created_at')
|
||||
.defaultTo(knex.fn.now());
|
||||
}))
|
||||
.then(() => knex.schema.createTable('tags_posters', (table) => {
|
||||
table.integer('tag_id', 12)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('tags');
|
||||
|
||||
table.integer('media_id', 16)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('media');
|
||||
|
||||
table.unique('tag_id');
|
||||
}))
|
||||
.then(() => knex.schema.createTable('tags_photos', (table) => {
|
||||
table.integer('tag_id', 12)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('tags');
|
||||
|
||||
table.integer('media_id', 16)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('media');
|
||||
|
||||
table.unique(['tag_id', 'media_id']);
|
||||
}))
|
||||
.then(() => knex.schema.createTable('networks', (table) => {
|
||||
table.increments('id', 12);
|
||||
|
||||
table.string('name');
|
||||
table.string('url');
|
||||
table.text('description');
|
||||
table.string('parameters');
|
||||
|
||||
table.string('slug', 32)
|
||||
.unique();
|
||||
|
||||
table.datetime('created_at')
|
||||
.defaultTo(knex.fn.now());
|
||||
}))
|
||||
.then(() => knex.schema.createTable('networks_social', (table) => {
|
||||
table.increments('id', 16);
|
||||
|
||||
table.string('url');
|
||||
table.string('platform');
|
||||
|
||||
table.integer('network_id', 12)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('networks');
|
||||
|
||||
table.unique(['url', 'network_id']);
|
||||
|
||||
table.datetime('created_at')
|
||||
.defaultTo(knex.fn.now());
|
||||
}))
|
||||
.then(() => knex.schema.createTable('sites', (table) => {
|
||||
table.increments('id', 12);
|
||||
|
||||
table.integer('network_id', 12)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('networks');
|
||||
|
||||
table.string('name');
|
||||
table.string('url');
|
||||
table.text('description');
|
||||
table.string('parameters');
|
||||
|
||||
table.string('slug', 32)
|
||||
.unique();
|
||||
|
||||
table.datetime('created_at')
|
||||
.defaultTo(knex.fn.now());
|
||||
}))
|
||||
.then(() => knex.schema.createTable('sites_tags', (table) => {
|
||||
table.integer('tag_id', 12)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('tags');
|
||||
|
||||
table.integer('site_id', 12)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('sites');
|
||||
|
||||
table.unique(['tag_id', 'site_id']);
|
||||
}))
|
||||
.then(() => knex.schema.createTable('sites_social', (table) => {
|
||||
table.increments('id', 16);
|
||||
|
||||
table.string('url');
|
||||
table.string('platform');
|
||||
|
||||
table.integer('site_id', 12)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('sites');
|
||||
|
||||
table.unique(['url', 'site_id']);
|
||||
|
||||
table.datetime('created_at')
|
||||
.defaultTo(knex.fn.now());
|
||||
}))
|
||||
.then(() => knex.schema.createTable('studios', (table) => {
|
||||
table.increments('id', 12);
|
||||
|
||||
table.integer('network_id', 12)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('networks');
|
||||
|
||||
table.string('name');
|
||||
table.string('url');
|
||||
table.text('description');
|
||||
|
||||
table.string('slug', 32)
|
||||
.unique();
|
||||
|
||||
table.datetime('created_at')
|
||||
.defaultTo(knex.fn.now());
|
||||
}))
|
||||
.then(() => knex.schema.createTable('actors', (table) => {
|
||||
table.increments('id', 12);
|
||||
|
||||
|
@ -70,6 +248,48 @@ exports.up = knex => Promise.resolve()
|
|||
table.datetime('scraped_at');
|
||||
table.boolean('scrape_success');
|
||||
}))
|
||||
.then(() => knex.schema.createTable('actors_avatars', (table) => {
|
||||
table.integer('actor_id', 12)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('actors');
|
||||
|
||||
table.integer('media_id', 16)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('media');
|
||||
|
||||
table.unique('actor_id');
|
||||
}))
|
||||
.then(() => knex.schema.createTable('actors_photos', (table) => {
|
||||
table.integer('actor_id', 12)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('actors');
|
||||
|
||||
table.integer('media_id', 16)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('media');
|
||||
|
||||
table.unique(['actor_id', 'media_id']);
|
||||
}))
|
||||
.then(() => knex.schema.createTable('actors_social', (table) => {
|
||||
table.increments('id', 16);
|
||||
|
||||
table.string('url');
|
||||
table.string('platform');
|
||||
|
||||
table.integer('actor_id', 8)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('actors');
|
||||
|
||||
table.unique(['url', 'actor_id']);
|
||||
|
||||
table.datetime('created_at')
|
||||
.defaultTo(knex.fn.now());
|
||||
}))
|
||||
.then(() => knex.schema.createTable('directors', (table) => {
|
||||
table.increments('id', 12);
|
||||
|
||||
|
@ -84,92 +304,6 @@ exports.up = knex => Promise.resolve()
|
|||
table.datetime('created_at')
|
||||
.defaultTo(knex.fn.now());
|
||||
}))
|
||||
.then(() => knex.schema.createTable('tags_groups', (table) => {
|
||||
table.increments('id', 12);
|
||||
|
||||
table.string('name', 32);
|
||||
table.text('description');
|
||||
|
||||
table.string('slug', 32)
|
||||
.unique();
|
||||
|
||||
table.datetime('created_at')
|
||||
.defaultTo(knex.fn.now());
|
||||
}))
|
||||
.then(() => knex.schema.createTable('tags', (table) => {
|
||||
table.increments('id', 12);
|
||||
table.string('name');
|
||||
|
||||
table.text('description');
|
||||
|
||||
table.integer('priority', 2)
|
||||
.defaultTo(0);
|
||||
|
||||
table.integer('group_id', 12)
|
||||
.references('id')
|
||||
.inTable('tags_groups');
|
||||
|
||||
table.integer('alias_for', 12)
|
||||
.references('id')
|
||||
.inTable('tags');
|
||||
|
||||
table.string('slug', 32)
|
||||
.unique();
|
||||
|
||||
table.datetime('created_at')
|
||||
.defaultTo(knex.fn.now());
|
||||
}))
|
||||
.then(() => knex.schema.createTable('networks', (table) => {
|
||||
table.increments('id', 12);
|
||||
|
||||
table.string('name');
|
||||
table.string('url');
|
||||
table.text('description');
|
||||
table.string('parameters');
|
||||
|
||||
table.string('slug', 32)
|
||||
.unique();
|
||||
|
||||
table.datetime('created_at')
|
||||
.defaultTo(knex.fn.now());
|
||||
}))
|
||||
.then(() => knex.schema.createTable('sites', (table) => {
|
||||
table.increments('id', 12);
|
||||
|
||||
table.integer('network_id', 12)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('networks');
|
||||
|
||||
table.string('name');
|
||||
table.string('url');
|
||||
table.text('description');
|
||||
table.string('parameters');
|
||||
|
||||
table.string('slug', 32)
|
||||
.unique();
|
||||
|
||||
table.datetime('created_at')
|
||||
.defaultTo(knex.fn.now());
|
||||
}))
|
||||
.then(() => knex.schema.createTable('studios', (table) => {
|
||||
table.increments('id', 12);
|
||||
|
||||
table.integer('network_id', 12)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('networks');
|
||||
|
||||
table.string('name');
|
||||
table.string('url');
|
||||
table.text('description');
|
||||
|
||||
table.string('slug', 32)
|
||||
.unique();
|
||||
|
||||
table.datetime('created_at')
|
||||
.defaultTo(knex.fn.now());
|
||||
}))
|
||||
.then(() => knex.schema.createTable('releases', (table) => {
|
||||
table.increments('id', 16);
|
||||
|
||||
|
@ -193,10 +327,6 @@ exports.up = knex => Promise.resolve()
|
|||
table.date('date');
|
||||
table.text('description');
|
||||
|
||||
table.integer('director', 12)
|
||||
.references('id')
|
||||
.inTable('directors');
|
||||
|
||||
table.integer('duration')
|
||||
.unsigned();
|
||||
|
||||
|
@ -209,48 +339,7 @@ exports.up = knex => Promise.resolve()
|
|||
table.datetime('created_at')
|
||||
.defaultTo(knex.fn.now());
|
||||
}))
|
||||
.then(() => knex.schema.createTable('media', (table) => {
|
||||
table.increments('id', 16);
|
||||
|
||||
table.string('path');
|
||||
table.string('thumbnail');
|
||||
table.integer('index');
|
||||
table.string('mime');
|
||||
|
||||
table.string('domain');
|
||||
table.integer('target_id', 16);
|
||||
|
||||
table.json('target');
|
||||
|
||||
table.string('role');
|
||||
table.string('quality', 6);
|
||||
|
||||
table.string('hash');
|
||||
table.text('comment');
|
||||
table.string('source', 1000);
|
||||
|
||||
table.unique(['domain', 'target_id', 'role', 'hash']);
|
||||
|
||||
table.datetime('created_at')
|
||||
.defaultTo(knex.fn.now());
|
||||
}))
|
||||
.then(() => knex.schema.createTable('social', (table) => {
|
||||
table.increments('id', 16);
|
||||
|
||||
table.string('url');
|
||||
table.string('platform');
|
||||
|
||||
table.string('domain');
|
||||
table.integer('target_id', 16);
|
||||
|
||||
table.unique(['url', 'domain', 'target_id']);
|
||||
|
||||
table.datetime('created_at')
|
||||
.defaultTo(knex.fn.now());
|
||||
}))
|
||||
.then(() => knex.schema.createTable('actors_associated', (table) => {
|
||||
// table.increments('id', 16);
|
||||
|
||||
.then(() => knex.schema.createTable('releases_actors', (table) => {
|
||||
table.integer('release_id', 16)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
|
@ -263,9 +352,7 @@ exports.up = knex => Promise.resolve()
|
|||
|
||||
table.unique(['release_id', 'actor_id']);
|
||||
}))
|
||||
.then(() => knex.schema.createTable('directors_associated', (table) => {
|
||||
table.increments('id', 16);
|
||||
|
||||
.then(() => knex.schema.createTable('releases_directors', (table) => {
|
||||
table.integer('release_id', 16)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
|
@ -278,65 +365,85 @@ exports.up = knex => Promise.resolve()
|
|||
|
||||
table.unique(['release_id', 'director_id']);
|
||||
}))
|
||||
.then(() => knex.schema.createTable('tags_associated', (table) => {
|
||||
.then(() => knex.schema.createTable('releases_posters', (table) => {
|
||||
table.integer('release_id', 16)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('releases');
|
||||
|
||||
table.integer('media_id', 16)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('media');
|
||||
|
||||
table.unique('release_id');
|
||||
}))
|
||||
.then(() => knex.schema.createTable('releases_photos', (table) => {
|
||||
table.integer('release_id', 16)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('releases');
|
||||
|
||||
table.integer('media_id', 16)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('media');
|
||||
|
||||
table.unique(['release_id', 'media_id']);
|
||||
}))
|
||||
.then(() => knex.schema.createTable('releases_tags', (table) => {
|
||||
table.integer('tag_id', 12)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('tags');
|
||||
|
||||
table.string('domain');
|
||||
table.integer('target_id', 16);
|
||||
table.integer('release_id', 16)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('releases');
|
||||
|
||||
table.unique(['domain', 'tag_id', 'target_id']);
|
||||
table.unique(['tag_id', 'release_id']);
|
||||
}))
|
||||
.then(() => knex.raw(`
|
||||
CREATE VIEW releases_media AS SELECT * FROM media WHERE domain = 'releases';
|
||||
CREATE VIEW actors_media AS SELECT * FROM media WHERE domain = 'actors';
|
||||
CREATE VIEW tags_media AS SELECT * FROM media WHERE domain = 'tags';
|
||||
|
||||
CREATE VIEW releases_tags AS SELECT tags_associated.*,tags.slug FROM tags_associated LEFT JOIN tags ON tags_associated.tag_id = tags.id WHERE domain = 'releases';
|
||||
/* used for sorting release actors and tags */
|
||||
CREATE VIEW releases_actors AS SELECT actors_associated.*,actors.gender,actors.birthdate FROM actors_associated LEFT JOIN actors ON actors_associated.actor_id = actors.id;
|
||||
|
||||
CREATE VIEW actors_social AS SELECT * FROM social WHERE domain = 'actors';
|
||||
|
||||
COMMENT ON VIEW releases_media IS E'@foreignKey (target_id) references releases (id)|@fieldName releaseMedia';
|
||||
COMMENT ON VIEW actors_media IS E'@foreignKey (target_id) references actors (id)|@fieldName actorMedia';
|
||||
COMMENT ON VIEW tags_media IS E'@foreignKey (target_id) references tags (id)|@fieldName tagMedia';
|
||||
|
||||
COMMENT ON VIEW actors_social IS E'@foreignKey (target_id) references actors (id)|@fieldName actorSocial';
|
||||
|
||||
COMMENT ON VIEW releases_tags IS E'@foreignKey (target_id) references releases (id)|@fieldName tagRelease\n@foreignKey (tag_id) references tags (id)|@fieldName releaseTag';
|
||||
|
||||
/* restore foreign keys in view, used for sorting release actors */
|
||||
COMMENT ON VIEW releases_actors IS E'@foreignKey (release_id) references releases (id)|@fieldName actorRelease\n@foreignKey (actor_id) references actors (id)|@fieldName releaseActor';
|
||||
|
||||
/* allow conversion resolver to be added for height and weight */
|
||||
COMMENT ON COLUMN actors.height IS E'@omit read,update,create,delete,all,many';
|
||||
COMMENT ON COLUMN actors.weight IS E'@omit read,update,create,delete,all,many';
|
||||
|
||||
/*
|
||||
create function releases_by_tag_slugs(slugs text[]) returns setof releases as $$
|
||||
select distinct on (releases.id) releases.* from releases
|
||||
join releases_tags on (releases_tags.release_id = releases.id)
|
||||
join tags on (releases_tags.tag_id = tags.id)
|
||||
where tags.slug = ANY($1);
|
||||
$$ language sql stable
|
||||
*/
|
||||
`));
|
||||
|
||||
exports.down = knex => Promise.resolve()
|
||||
.then(() => knex.raw(`
|
||||
DROP VIEW releases_media;
|
||||
DROP VIEW actors_media;
|
||||
DROP VIEW tags_media;
|
||||
exports.down = knex => knex.raw(`
|
||||
DROP FUNCTION IF EXISTS releases_by_tag_slugs;
|
||||
|
||||
DROP VIEW releases_tags;
|
||||
DROP VIEW releases_actors;
|
||||
|
||||
DROP VIEW actors_social;
|
||||
`))
|
||||
.then(() => knex.schema.dropTable('tags_associated'))
|
||||
.then(() => knex.schema.dropTable('directors_associated'))
|
||||
.then(() => knex.schema.dropTable('actors_associated'))
|
||||
.then(() => knex.schema.dropTable('tags'))
|
||||
.then(() => knex.schema.dropTable('tags_groups'))
|
||||
.then(() => knex.schema.dropTable('media'))
|
||||
.then(() => knex.schema.dropTable('social'))
|
||||
.then(() => knex.schema.dropTable('actors'))
|
||||
.then(() => knex.schema.dropTable('releases'))
|
||||
.then(() => knex.schema.dropTable('sites'))
|
||||
.then(() => knex.schema.dropTable('studios'))
|
||||
.then(() => knex.schema.dropTable('directors'))
|
||||
.then(() => knex.schema.dropTable('networks'))
|
||||
.then(() => knex.schema.dropTable('countries'));
|
||||
DROP TABLE IF EXISTS releases_actors CASCADE;
|
||||
DROP TABLE IF EXISTS releases_directors CASCADE;
|
||||
DROP TABLE IF EXISTS releases_posters CASCADE;
|
||||
DROP TABLE IF EXISTS releases_photos CASCADE;
|
||||
DROP TABLE IF EXISTS releases_tags CASCADE;
|
||||
DROP TABLE IF EXISTS actors_avatars CASCADE;
|
||||
DROP TABLE IF EXISTS actors_photos CASCADE;
|
||||
DROP TABLE IF EXISTS actors_social CASCADE;
|
||||
DROP TABLE IF EXISTS sites_tags CASCADE;
|
||||
DROP TABLE IF EXISTS sites_social CASCADE;
|
||||
DROP TABLE IF EXISTS networks_social CASCADE;
|
||||
DROP TABLE IF EXISTS tags_posters CASCADE;
|
||||
DROP TABLE IF EXISTS tags_photos CASCADE;
|
||||
DROP TABLE IF EXISTS releases CASCADE;
|
||||
DROP TABLE IF EXISTS actors CASCADE;
|
||||
DROP TABLE IF EXISTS directors CASCADE;
|
||||
DROP TABLE IF EXISTS tags CASCADE;
|
||||
DROP TABLE IF EXISTS tags_groups CASCADE;
|
||||
DROP TABLE IF EXISTS social CASCADE;
|
||||
DROP TABLE IF EXISTS sites CASCADE;
|
||||
DROP TABLE IF EXISTS studios CASCADE;
|
||||
DROP TABLE IF EXISTS media CASCADE;
|
||||
DROP TABLE IF EXISTS countries CASCADE;
|
||||
DROP TABLE IF EXISTS networks CASCADE;
|
||||
`);
|
||||
|
|
|
@ -125,10 +125,4 @@ const networks = [
|
|||
];
|
||||
|
||||
exports.seed = knex => Promise.resolve()
|
||||
.then(async () => {
|
||||
// find network IDs
|
||||
const duplicates = await knex('networks').select('*');
|
||||
const duplicatesBySlug = duplicates.reduce((acc, network) => ({ ...acc, [network.slug]: network }), {});
|
||||
|
||||
return upsert('networks', networks, duplicatesBySlug, 'slug', knex);
|
||||
});
|
||||
.then(async () => upsert('networks', networks, 'slug', knex));
|
||||
|
|
|
@ -2428,15 +2428,10 @@ function getSites(networksMap) {
|
|||
/* eslint-disable max-len */
|
||||
exports.seed = knex => Promise.resolve()
|
||||
.then(async () => {
|
||||
const [duplicates, networks] = await Promise.all([
|
||||
knex('sites').select('*'),
|
||||
knex('networks').select('*'),
|
||||
]);
|
||||
|
||||
const duplicatesBySlug = duplicates.reduce((acc, site) => ({ ...acc, [site.slug]: site }), {});
|
||||
const networks = await knex('networks').select('*');
|
||||
const networksMap = networks.reduce((acc, { id, slug }) => ({ ...acc, [slug]: id }), {});
|
||||
|
||||
const sites = getSites(networksMap);
|
||||
|
||||
return upsert('sites', sites, duplicatesBySlug, 'slug', knex);
|
||||
return upsert('sites', sites, 'slug', knex);
|
||||
});
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
'use strict';
|
||||
|
||||
const upsert = require('../src/utils/upsert');
|
||||
|
||||
function getStudios(networksMap) {
|
||||
|
@ -9,133 +7,133 @@ function getStudios(networksMap) {
|
|||
slug: 'gonzocom',
|
||||
name: 'Gonzo.com',
|
||||
url: 'https://www.legalporno.com/studios/gonzo_com',
|
||||
network_id: networksMap['legalporno'],
|
||||
network_id: networksMap.legalporno,
|
||||
},
|
||||
{
|
||||
slug: 'giorgiograndi',
|
||||
name: 'Giorgio Grandi',
|
||||
url: 'https://www.legalporno.com/studios/giorgio-grandi',
|
||||
network_id: networksMap['legalporno'],
|
||||
network_id: networksMap.legalporno,
|
||||
},
|
||||
{
|
||||
slug: 'hardpornworld',
|
||||
name: 'Hard Porn World',
|
||||
url: 'https://www.legalporno.com/studios/hard-porn-world',
|
||||
network_id: networksMap['legalporno'],
|
||||
network_id: networksMap.legalporno,
|
||||
},
|
||||
{
|
||||
slug: 'interracialvision',
|
||||
name: 'Interracial Vision',
|
||||
url: 'https://www.legalporno.com/studios/interracial-vision',
|
||||
network_id: networksMap['legalporno'],
|
||||
network_id: networksMap.legalporno,
|
||||
},
|
||||
{
|
||||
slug: 'giorgioslab',
|
||||
name: 'Giorgio\'s Lab',
|
||||
url: 'https://www.legalporno.com/studios/giorgio--s-lab',
|
||||
network_id: networksMap['legalporno'],
|
||||
network_id: networksMap.legalporno,
|
||||
},
|
||||
{
|
||||
slug: 'americananal',
|
||||
name: 'American Anal',
|
||||
url: 'https://www.legalporno.com/studios/american-anal',
|
||||
network_id: networksMap['legalporno'],
|
||||
network_id: networksMap.legalporno,
|
||||
},
|
||||
{
|
||||
slug: 'assablanca',
|
||||
name: 'Assablanca',
|
||||
url: 'https://www.legalporno.com/studios/assablanca',
|
||||
network_id: networksMap['legalporno'],
|
||||
network_id: networksMap.legalporno,
|
||||
},
|
||||
{
|
||||
slug: 'focus',
|
||||
name: 'Focus',
|
||||
url: 'https://www.legalporno.com/studios/focus',
|
||||
network_id: networksMap['legalporno'],
|
||||
network_id: networksMap.legalporno,
|
||||
},
|
||||
{
|
||||
slug: 'analforever',
|
||||
name: 'Anal Forever',
|
||||
url: 'https://www.legalporno.com/studios/anal-forever',
|
||||
network_id: networksMap['legalporno'],
|
||||
network_id: networksMap.legalporno,
|
||||
},
|
||||
{
|
||||
slug: 'gonzoinbrazil',
|
||||
name: 'Gonzo in Brazil',
|
||||
url: 'https://www.legalporno.com/studios/gonzo-in-brazil',
|
||||
network_id: networksMap['legalporno'],
|
||||
network_id: networksMap.legalporno,
|
||||
},
|
||||
{
|
||||
slug: 'mranal',
|
||||
name: 'Mr Anal',
|
||||
url: 'https://www.legalporno.com/studios/mr-anal',
|
||||
network_id: networksMap['legalporno'],
|
||||
network_id: networksMap.legalporno,
|
||||
},
|
||||
{
|
||||
slug: 'tarrawhite',
|
||||
name: 'Tarra White',
|
||||
url: 'https://www.legalporno.com/studios/tarra-white',
|
||||
network_id: networksMap['legalporno'],
|
||||
network_id: networksMap.legalporno,
|
||||
},
|
||||
{
|
||||
slug: 'sineplexsos',
|
||||
name: 'Sineplex SOS',
|
||||
url: 'https://www.legalporno.com/studios/sineplex-sos',
|
||||
network_id: networksMap['legalporno'],
|
||||
network_id: networksMap.legalporno,
|
||||
},
|
||||
{
|
||||
slug: 'fmodels',
|
||||
name: 'F Models',
|
||||
url: 'https://www.legalporno.com/studios/f-models',
|
||||
network_id: networksMap['legalporno'],
|
||||
network_id: networksMap.legalporno,
|
||||
},
|
||||
{
|
||||
slug: 'sineplexcz',
|
||||
name: 'Sineplex CZ',
|
||||
url: 'https://www.legalporno.com/studios/sineplex-cz',
|
||||
network_id: networksMap['legalporno'],
|
||||
network_id: networksMap.legalporno,
|
||||
},
|
||||
{
|
||||
slug: 'gg',
|
||||
name: 'GG',
|
||||
url: 'https://www.legalporno.com/studios/gg',
|
||||
network_id: networksMap['legalporno'],
|
||||
network_id: networksMap.legalporno,
|
||||
},
|
||||
{
|
||||
slug: 'firstgape',
|
||||
name: 'First Gape',
|
||||
url: 'https://www.legalporno.com/studios/first-gape',
|
||||
network_id: networksMap['legalporno'],
|
||||
network_id: networksMap.legalporno,
|
||||
},
|
||||
{
|
||||
slug: 'omargalantiproductions',
|
||||
name: 'Omar Galanti Productions',
|
||||
url: 'https://www.legalporno.com/studios/omar-galanti-productions',
|
||||
network_id: networksMap['legalporno'],
|
||||
network_id: networksMap.legalporno,
|
||||
},
|
||||
{
|
||||
slug: 'norestfortheass',
|
||||
name: 'No Rest For The Ass',
|
||||
url: 'https://www.legalporno.com/studios/no-rest-for-the-ass',
|
||||
network_id: networksMap['legalporno'],
|
||||
network_id: networksMap.legalporno,
|
||||
},
|
||||
{
|
||||
slug: 'hairygonzo',
|
||||
name: 'Hairy Gonzo',
|
||||
url: 'https://www.legalporno.com/studios/hairy-gonzo',
|
||||
network_id: networksMap['legalporno'],
|
||||
network_id: networksMap.legalporno,
|
||||
},
|
||||
{
|
||||
slug: 'sineplexclassic',
|
||||
name: 'Sineplex Classic',
|
||||
url: 'https://www.legalporno.com/studios/sineplex-classic',
|
||||
network_id: networksMap['legalporno'],
|
||||
network_id: networksMap.legalporno,
|
||||
},
|
||||
{
|
||||
slug: 'sinemale',
|
||||
name: 'Sinemale',
|
||||
url: 'https://www.legalporno.com/studios/sinemale',
|
||||
network_id: networksMap['legalporno'],
|
||||
network_id: networksMap.legalporno,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
@ -143,15 +141,10 @@ function getStudios(networksMap) {
|
|||
/* eslint-disable max-len */
|
||||
exports.seed = knex => Promise.resolve()
|
||||
.then(async () => {
|
||||
const [duplicates, networks] = await Promise.all([
|
||||
knex('studios').select('*'),
|
||||
knex('networks').select('*'),
|
||||
]);
|
||||
|
||||
const duplicatesBySlug = duplicates.reduce((acc, studio) => ({ ...acc, [studio.slug]: studio }), {});
|
||||
const networks = await knex('networks').select('*');
|
||||
const networksMap = networks.reduce((acc, { id, slug }) => ({ ...acc, [slug]: id }), {});
|
||||
|
||||
const studios = getStudios(networksMap);
|
||||
|
||||
return upsert('studios', studios, duplicatesBySlug, 'slug', knex);
|
||||
return upsert('studios', studios, 'slug', knex);
|
||||
});
|
||||
|
|
|
@ -69,7 +69,7 @@ function getTags(groupsMap) {
|
|||
name: 'airtight',
|
||||
slug: 'airtight',
|
||||
alias_for: null,
|
||||
description: 'Stuffing one cock in her ass, one in her pussy, and one in her mouth, filling all of her penetrable holes and sealing her airtight like a figurative balloon. In other words, simultaneously getting [double penetrated](/tag/double-penetration), and giving a [blowjob](/tag/blowjob) or getting [facefucked](/tag/facefuck). Being airtight implies being [gangbanged](/tag/gangbang).',
|
||||
description: 'Stuffing one cock in her ass, one in her pussy, and one in her mouth, filling all of her penetrable holes and sealing her airtight like a figurative balloon. In other words, simultaneously getting [double penetrated](/tag/double-penetration), and giving a [blowjob](/tag/blowjob) or getting [facefucked](/tag/facefuck). Being airtight implies being [gangbanged](/tag/gangbang).', /* eslint-disable-line max-len */
|
||||
priority: 9,
|
||||
group_id: groupsMap.penetration,
|
||||
},
|
||||
|
@ -429,7 +429,7 @@ function getTags(groupsMap) {
|
|||
{
|
||||
name: 'gangbang',
|
||||
slug: 'gangbang',
|
||||
description: 'A group of three or more guys fucking a woman, at least two at the same time, often but not necessarily involving a [blowbang](/tag/blowbang), [double penetration](/tag/airtight) and [airtight](/tag/airtight). If she only gets fucked by one guy at a time, it might be considered a [trainbang](/tag/trainbang) instead. In a reverse gangbang, multiple women fuck one man.',
|
||||
description: 'A group of three or more guys fucking a woman, at least two at the same time, often but not necessarily involving a [blowbang](/tag/blowbang), [double penetration](/tag/airtight) and [airtight](/tag/airtight). If she only gets fucked by one guy at a time, it might be considered a [trainbang](/tag/trainbang) instead. In a reverse gangbang, multiple women fuck one man.', /* eslint-disable-line max-len */
|
||||
alias_for: null,
|
||||
priority: 9,
|
||||
group_id: groupsMap.group,
|
||||
|
@ -1542,35 +1542,20 @@ function getTagAliases(tagsMap) {
|
|||
}
|
||||
|
||||
exports.seed = knex => Promise.resolve()
|
||||
.then(async () => upsert('tags_groups', groups, 'slug', knex))
|
||||
.then(async () => {
|
||||
const duplicates = await knex('tags_groups').select('*');
|
||||
const duplicatesBySlug = duplicates.reduce((acc, group) => ({ ...acc, [group.slug]: group }), {});
|
||||
|
||||
return upsert('tags_groups', groups, duplicatesBySlug, 'slug', knex);
|
||||
})
|
||||
.then(async () => {
|
||||
const [duplicates, groupEntries] = await Promise.all([
|
||||
knex('tags').select('*'),
|
||||
knex('tags_groups').select('*'),
|
||||
]);
|
||||
|
||||
const duplicatesBySlug = duplicates.reduce((acc, tag) => ({ ...acc, [tag.slug]: tag }), {});
|
||||
const groupEntries = knex('tags').select('*');
|
||||
const groupsMap = groupEntries.reduce((acc, { id, slug }) => ({ ...acc, [slug]: id }), {});
|
||||
|
||||
const tags = getTags(groupsMap);
|
||||
|
||||
return upsert('tags', tags, duplicatesBySlug, 'slug', knex);
|
||||
return upsert('tags', tags, 'slug', knex);
|
||||
})
|
||||
.then(async () => {
|
||||
const [duplicates, tags] = await Promise.all([
|
||||
knex('tags').select('*').whereNotNull('alias_for'),
|
||||
knex('tags').select('*').where({ alias_for: null }),
|
||||
]);
|
||||
|
||||
const duplicatesByName = duplicates.reduce((acc, tag) => ({ ...acc, [tag.name]: tag }), {});
|
||||
const tags = await knex('tags').select('*').where({ alias_for: null });
|
||||
const tagsMap = tags.reduce((acc, { id, slug }) => ({ ...acc, [slug]: id }), {});
|
||||
|
||||
const tagAliases = getTagAliases(tagsMap);
|
||||
|
||||
return upsert('tags', tagAliases, duplicatesByName, 'name', knex);
|
||||
return upsert('tags', tagAliases, 'name', knex);
|
||||
});
|
||||
|
|
|
@ -1,231 +1,119 @@
|
|||
const upsert = require('../src/utils/upsert');
|
||||
|
||||
function getMedia(tagsMap) {
|
||||
return [
|
||||
const tagPosters = [
|
||||
{
|
||||
path: 'tags/airtight/poster.jpeg',
|
||||
target_id: tagsMap.airtight,
|
||||
role: 'poster',
|
||||
tagSlug: 'airtight',
|
||||
comment: 'Jynx Maze in "Pump My Ass Full of Cum 3" for Jules Jordan',
|
||||
},
|
||||
{
|
||||
path: 'tags/airtight/2.jpeg',
|
||||
target_id: tagsMap.airtight,
|
||||
comment: 'Dakota Skye in "Dakota Goes Nuts" for ArchAngel',
|
||||
},
|
||||
{
|
||||
path: 'tags/airtight/1.jpeg',
|
||||
target_id: tagsMap.airtight,
|
||||
comment: 'Chloe Amour in "DP Masters 4" for Jules Jordan',
|
||||
},
|
||||
{
|
||||
path: 'tags/airtight/0.jpeg',
|
||||
domain: 'tags',
|
||||
target_id: tagsMap.airtight,
|
||||
comment: 'Sheena Shaw in "Ass Worship 14" for Jules Jordan',
|
||||
},
|
||||
{
|
||||
path: 'tags/anal/poster.jpeg',
|
||||
target_id: tagsMap.anal,
|
||||
role: 'poster',
|
||||
tagSlug: 'anal',
|
||||
comment: '',
|
||||
},
|
||||
{
|
||||
path: 'tags/double-penetration/poster.jpeg',
|
||||
target_id: tagsMap['double-penetration'],
|
||||
role: 'poster',
|
||||
tagSlug: 'double-penetration',
|
||||
comment: '',
|
||||
},
|
||||
{
|
||||
path: 'tags/double-anal/poster.jpeg',
|
||||
target_id: tagsMap['double-anal'],
|
||||
role: 'poster',
|
||||
tagSlug: 'double-anal',
|
||||
comment: '',
|
||||
},
|
||||
{
|
||||
path: 'tags/double-vaginal/poster.jpeg',
|
||||
target_id: tagsMap['double-vaginal'],
|
||||
role: 'poster',
|
||||
tagSlug: 'double-vaginal',
|
||||
comment: '',
|
||||
},
|
||||
{
|
||||
path: 'tags/da-tp/0.jpeg',
|
||||
target_id: tagsMap['da-tp'],
|
||||
role: 'poster',
|
||||
comment: 'Natasha Teen in LegalPorno SZ2164',
|
||||
},
|
||||
{
|
||||
path: 'tags/da-tp/3.jpeg',
|
||||
target_id: tagsMap['da-tp'],
|
||||
role: 'photo',
|
||||
comment: 'Evelina Darling in GIO294',
|
||||
},
|
||||
{
|
||||
path: 'tags/da-tp/1.jpeg',
|
||||
target_id: tagsMap['da-tp'],
|
||||
role: 'photo',
|
||||
comment: 'Francys Belle in SZ1702 for LegalPorno',
|
||||
},
|
||||
{
|
||||
path: 'tags/da-tp/2.jpeg',
|
||||
target_id: tagsMap['da-tp'],
|
||||
role: 'photo',
|
||||
comment: 'Angel Smalls in GIO408 for LegalPorno',
|
||||
},
|
||||
{
|
||||
path: 'tags/da-tp/4.jpeg',
|
||||
target_id: tagsMap['da-tp'],
|
||||
role: 'photo',
|
||||
comment: 'Ninel Mojado aka Mira Cuckold in GIO063 for LegalPorno',
|
||||
},
|
||||
{
|
||||
path: 'tags/dv-tp/poster.jpeg',
|
||||
target_id: tagsMap['dv-tp'],
|
||||
role: 'poster',
|
||||
comment: 'Juelz Ventura in "Gangbanged 5" for Elegant Angel',
|
||||
},
|
||||
{
|
||||
path: 'tags/dv-tp/0.jpeg',
|
||||
target_id: tagsMap['dv-tp'],
|
||||
role: 'photo',
|
||||
comment: 'Luna Rival in LegalPorno SZ1490',
|
||||
},
|
||||
{
|
||||
path: 'tags/tattoo/poster.jpeg',
|
||||
target_id: tagsMap.tattoo,
|
||||
role: 'poster',
|
||||
tagSlug: 'tattoo',
|
||||
comment: 'Kali Roses in "Goes All In For Anal" for Hussie Pass',
|
||||
},
|
||||
{
|
||||
path: 'tags/triple-anal/poster.jpeg',
|
||||
target_id: tagsMap['triple-anal'],
|
||||
role: 'poster',
|
||||
tagSlug: 'triple-anal',
|
||||
comment: 'Kristy Black in SZ1986 for LegalPorno',
|
||||
},
|
||||
{
|
||||
path: 'tags/triple-anal/1.jpeg',
|
||||
target_id: tagsMap['triple-anal'],
|
||||
role: 'photo',
|
||||
comment: 'Natasha Teen in SZ2098 for LegalPorno',
|
||||
},
|
||||
{
|
||||
path: 'tags/triple-anal/2.jpeg',
|
||||
target_id: tagsMap['triple-anal'],
|
||||
role: 'photo',
|
||||
comment: 'Kira Thorn in GIO1018 for LegalPorno',
|
||||
},
|
||||
{
|
||||
path: 'tags/blowbang/poster.jpeg',
|
||||
target_id: tagsMap.blowbang,
|
||||
role: 'poster',
|
||||
tagSlug: 'blowbang',
|
||||
comment: '',
|
||||
},
|
||||
{
|
||||
path: 'tags/gangbang/poster.jpeg',
|
||||
target_id: tagsMap.gangbang,
|
||||
role: 'poster',
|
||||
tagSlug: 'gangbang',
|
||||
comment: '',
|
||||
},
|
||||
{
|
||||
path: 'tags/gangbang/1.jpeg',
|
||||
target_id: tagsMap.gangbang,
|
||||
role: 'photo',
|
||||
comment: 'Ginger Lynn in "Gangbang Mystique", a photoset shot by Suze Randall for Puritan No. 10, 1984. This photo pushed the boundaries of pornography at the time, as depicting a woman \'fully occupied\' was unheard of.',
|
||||
},
|
||||
{
|
||||
path: 'tags/gangbang/2.jpeg',
|
||||
target_id: tagsMap.gangbang,
|
||||
role: 'photo',
|
||||
comment: 'Riley Reid\'s double anal in "The Gangbang of Riley Reid" for Jules Jordan',
|
||||
},
|
||||
{
|
||||
path: 'tags/gangbang/3.jpeg',
|
||||
target_id: tagsMap.gangbang,
|
||||
role: 'photo',
|
||||
comment: 'Kelsi Monroe in "Brazzers House 2, Day 2" for Brazzers',
|
||||
},
|
||||
{
|
||||
path: 'tags/mff/poster.jpeg',
|
||||
target_id: tagsMap.mff,
|
||||
role: 'poster',
|
||||
tagSlug: 'mff',
|
||||
comment: '',
|
||||
},
|
||||
{
|
||||
path: 'tags/mfm/poster.jpeg',
|
||||
target_id: tagsMap.mfm,
|
||||
role: 'poster',
|
||||
tagSlug: 'mfm',
|
||||
comment: '',
|
||||
},
|
||||
{
|
||||
path: 'tags/orgy/poster.jpeg',
|
||||
target_id: tagsMap.orgy,
|
||||
role: 'poster',
|
||||
tagSlug: 'orgy',
|
||||
comment: '',
|
||||
},
|
||||
{
|
||||
path: 'tags/asian/poster.jpeg',
|
||||
target_id: tagsMap.asian,
|
||||
role: 'poster',
|
||||
tagSlug: 'asian',
|
||||
comment: '',
|
||||
},
|
||||
{
|
||||
path: 'tags/caucasian/poster.jpeg',
|
||||
target_id: tagsMap.caucasian,
|
||||
role: 'poster',
|
||||
tagSlug: 'caucasian',
|
||||
comment: '',
|
||||
},
|
||||
{
|
||||
path: 'tags/ebony/poster.jpeg',
|
||||
target_id: tagsMap.ebony,
|
||||
role: 'poster',
|
||||
tagSlug: 'ebony',
|
||||
comment: '',
|
||||
},
|
||||
{
|
||||
path: 'tags/latina/poster.jpeg',
|
||||
target_id: tagsMap.latina,
|
||||
role: 'poster',
|
||||
tagSlug: 'latina',
|
||||
comment: '',
|
||||
},
|
||||
{
|
||||
path: 'tags/interracial/poster.jpeg',
|
||||
target_id: tagsMap.interracial,
|
||||
role: 'poster',
|
||||
tagSlug: 'interracial',
|
||||
comment: '',
|
||||
},
|
||||
{
|
||||
path: 'tags/facial/poster.jpeg',
|
||||
target_id: tagsMap.facial,
|
||||
role: 'poster',
|
||||
tagSlug: 'facial',
|
||||
comment: '',
|
||||
},
|
||||
{
|
||||
path: 'tags/bukkake/poster.jpeg',
|
||||
target_id: tagsMap.bukkake,
|
||||
role: 'poster',
|
||||
tagSlug: 'bukkake',
|
||||
comment: '',
|
||||
},
|
||||
{
|
||||
path: 'tags/swallowing/poster.jpeg',
|
||||
target_id: tagsMap.swallowing,
|
||||
role: 'poster',
|
||||
tagSlug: 'swallowing',
|
||||
comment: '',
|
||||
},
|
||||
{
|
||||
path: 'tags/creampie/poster.jpeg',
|
||||
target_id: tagsMap.creampie,
|
||||
role: 'poster',
|
||||
tagSlug: 'creampie',
|
||||
comment: '',
|
||||
},
|
||||
{
|
||||
path: 'tags/anal-creampie/poster.jpeg',
|
||||
target_id: tagsMap['anal-creampie'],
|
||||
role: 'poster',
|
||||
tagSlug: 'anal-creampie',
|
||||
comment: '',
|
||||
},
|
||||
{
|
||||
path: 'tags/oral-creampie/poster.jpeg',
|
||||
target_id: tagsMap['oral-creampie'],
|
||||
role: 'poster',
|
||||
tagSlug: 'oral-creampie',
|
||||
comment: '',
|
||||
},
|
||||
]
|
||||
|
@ -234,24 +122,120 @@ function getMedia(tagsMap) {
|
|||
thumbnail: file.thumbnail || file.path.replace('.jpeg', '_thumb.jpeg'),
|
||||
mime: 'image/jpeg',
|
||||
index,
|
||||
domain: file.domain || 'tags',
|
||||
target: { [file.domain || 'tags']: file.target_id },
|
||||
role: file.role || 'photo',
|
||||
}));
|
||||
}
|
||||
|
||||
const tagPhotos = [
|
||||
{
|
||||
path: 'tags/airtight/2.jpeg',
|
||||
tagSlug: 'airtight',
|
||||
comment: 'Dakota Skye in "Dakota Goes Nuts" for ArchAngel',
|
||||
},
|
||||
{
|
||||
path: 'tags/airtight/1.jpeg',
|
||||
tagSlug: 'airtight',
|
||||
comment: 'Chloe Amour in "DP Masters 4" for Jules Jordan',
|
||||
},
|
||||
{
|
||||
path: 'tags/airtight/0.jpeg',
|
||||
domain: 'tags',
|
||||
tagSlug: 'airtight',
|
||||
comment: 'Sheena Shaw in "Ass Worship 14" for Jules Jordan',
|
||||
},
|
||||
{
|
||||
path: 'tags/da-tp/0.jpeg',
|
||||
tagSlug: 'da-tp',
|
||||
comment: 'Natasha Teen in LegalPorno SZ2164',
|
||||
},
|
||||
{
|
||||
path: 'tags/da-tp/3.jpeg',
|
||||
tagSlug: 'da-tp',
|
||||
comment: 'Evelina Darling in GIO294',
|
||||
},
|
||||
{
|
||||
path: 'tags/da-tp/1.jpeg',
|
||||
tagSlug: 'da-tp',
|
||||
comment: 'Francys Belle in SZ1702 for LegalPorno',
|
||||
},
|
||||
{
|
||||
path: 'tags/da-tp/2.jpeg',
|
||||
tagSlug: 'da-tp',
|
||||
comment: 'Angel Smalls in GIO408 for LegalPorno',
|
||||
},
|
||||
{
|
||||
path: 'tags/da-tp/4.jpeg',
|
||||
tagSlug: 'da-tp',
|
||||
comment: 'Ninel Mojado aka Mira Cuckold in GIO063 for LegalPorno',
|
||||
},
|
||||
{
|
||||
path: 'tags/dv-tp/poster.jpeg',
|
||||
tagSlug: 'dv-tp',
|
||||
comment: 'Juelz Ventura in "Gangbanged 5" for Elegant Angel',
|
||||
},
|
||||
{
|
||||
path: 'tags/dv-tp/0.jpeg',
|
||||
tagSlug: 'dv-tp',
|
||||
comment: 'Luna Rival in LegalPorno SZ1490',
|
||||
},
|
||||
{
|
||||
path: 'tags/triple-anal/1.jpeg',
|
||||
tagSlug: 'triple-anal',
|
||||
comment: 'Natasha Teen in SZ2098 for LegalPorno',
|
||||
},
|
||||
{
|
||||
path: 'tags/triple-anal/2.jpeg',
|
||||
tagSlug: 'triple-anal',
|
||||
comment: 'Kira Thorn in GIO1018 for LegalPorno',
|
||||
},
|
||||
{
|
||||
path: 'tags/gangbang/1.jpeg',
|
||||
tagSlug: 'gangbang',
|
||||
comment: 'Ginger Lynn in "Gangbang Mystique", a photoset shot by Suze Randall for Puritan No. 10, 1984. This photo pushed the boundaries of pornography at the time, as depicting a woman \'fully occupied\' was unheard of.',
|
||||
},
|
||||
{
|
||||
path: 'tags/gangbang/2.jpeg',
|
||||
tagSlug: 'gangbang',
|
||||
comment: 'Riley Reid\'s double anal in "The Gangbang of Riley Reid" for Jules Jordan',
|
||||
},
|
||||
{
|
||||
path: 'tags/gangbang/3.jpeg',
|
||||
tagSlug: 'gangbang',
|
||||
comment: 'Kelsi Monroe in "Brazzers House 2, Day 2" for Brazzers',
|
||||
},
|
||||
]
|
||||
.map((file, index) => ({
|
||||
...file,
|
||||
thumbnail: file.thumbnail || file.path.replace('.jpeg', '_thumb.jpeg'),
|
||||
mime: 'image/jpeg',
|
||||
index,
|
||||
}));
|
||||
|
||||
/* eslint-disable max-len */
|
||||
exports.seed = knex => Promise.resolve()
|
||||
.then(async () => {
|
||||
const [duplicates, tags] = await Promise.all([
|
||||
knex('media').where('domain', 'tags'),
|
||||
knex('tags').where('alias_for', null),
|
||||
const tagMedia = tagPosters.concat(tagPhotos);
|
||||
|
||||
const tags = await knex('tags').whereIn('slug', tagMedia.map(item => item.tagSlug));
|
||||
const { inserted, updated } = await upsert('media', tagMedia.map(({
|
||||
path, thumbnail, mime, index, comment,
|
||||
}) => ({
|
||||
path, thumbnail, mime, index, comment,
|
||||
})), 'path', knex);
|
||||
|
||||
const tagIdsBySlug = tags.reduce((acc, tag) => ({ ...acc, [tag.slug]: tag.id }), {});
|
||||
const mediaIdsByPath = inserted.concat(updated).reduce((acc, item) => ({ ...acc, [item.path]: item.id }), {});
|
||||
|
||||
const tagPosterEntries = tagPosters.map(poster => ({
|
||||
tag_id: tagIdsBySlug[poster.tagSlug],
|
||||
media_id: mediaIdsByPath[poster.path],
|
||||
}));
|
||||
|
||||
const tagPhotoEntries = tagPhotos.map(photo => ({
|
||||
tag_id: tagIdsBySlug[photo.tagSlug],
|
||||
media_id: mediaIdsByPath[photo.path],
|
||||
}));
|
||||
|
||||
return Promise.all([
|
||||
upsert('tags_posters', tagPosterEntries, 'tag_id', knex),
|
||||
upsert('tags_photos', tagPhotoEntries, 'tag_id', knex),
|
||||
]);
|
||||
|
||||
const duplicatesByPath = duplicates.reduce((acc, file) => ({ ...acc, [file.path]: file }), {});
|
||||
const tagsMap = tags.reduce((acc, { id, slug }) => ({ ...acc, [slug]: id }), {});
|
||||
|
||||
const media = getMedia(tagsMap);
|
||||
|
||||
return upsert('media', media, duplicatesByPath, 'path', knex);
|
||||
});
|
||||
|
|
|
@ -1755,9 +1755,4 @@ const countries = [
|
|||
];
|
||||
|
||||
exports.seed = knex => knex('countries')
|
||||
.then(async () => {
|
||||
const duplicates = await knex('countries').select('*');
|
||||
const duplicatesByAlpha2 = duplicates.reduce((acc, country) => ({ ...acc, [country.alpha2]: country }), {});
|
||||
|
||||
return upsert('countries', countries, duplicatesByAlpha2, 'alpha2', knex);
|
||||
});
|
||||
.then(async () => upsert('countries', countries, 'alpha2', knex));
|
||||
|
|
|
@ -1,29 +1,18 @@
|
|||
'use strict';
|
||||
|
||||
async function upsert(table, items, duplicatesById, identifier = 'id', knex) {
|
||||
async function upsert(table, items, identifier = 'id', knex) {
|
||||
const duplicates = await knex(table).whereIn(identifier, items.map(item => item[identifier]));
|
||||
const duplicatesByIdentifier = duplicates.reduce((acc, item) => ({ ...acc, [item[identifier]]: item }), {});
|
||||
|
||||
const { insert, update } = items.reduce((acc, item) => {
|
||||
if (duplicatesById[item[identifier]]) {
|
||||
return {
|
||||
...acc,
|
||||
update: [
|
||||
...acc.update,
|
||||
{
|
||||
...duplicatesById[item[identifier]],
|
||||
...item,
|
||||
},
|
||||
],
|
||||
};
|
||||
if (duplicatesByIdentifier[item[identifier]]) {
|
||||
acc.update.push(item);
|
||||
return acc;
|
||||
}
|
||||
|
||||
return {
|
||||
...acc,
|
||||
insert: [
|
||||
...acc.insert,
|
||||
item,
|
||||
],
|
||||
};
|
||||
},
|
||||
{
|
||||
acc.insert.push(item);
|
||||
return acc;
|
||||
}, {
|
||||
insert: [],
|
||||
update: [],
|
||||
});
|
||||
|
@ -32,13 +21,19 @@ async function upsert(table, items, duplicatesById, identifier = 'id', knex) {
|
|||
console.log(`${table}: Inserting ${insert.length}`);
|
||||
console.log(`${table}: Updating ${update.length}`);
|
||||
|
||||
return Promise.all([
|
||||
knex(table).insert(insert),
|
||||
const [inserted, updated] = await Promise.all([
|
||||
knex(table).returning('*').insert(insert),
|
||||
knex.transaction(async trx => Promise.all(update.map(item => trx
|
||||
.where({ [identifier]: item[identifier] })
|
||||
.update(item)
|
||||
.into(table)))),
|
||||
.into(table)
|
||||
.returning('*')))),
|
||||
]);
|
||||
|
||||
return {
|
||||
inserted: Array.isArray(inserted) ? inserted : [],
|
||||
updated: updated.reduce((acc, updatedItems) => acc.concat(updatedItems), []),
|
||||
};
|
||||
}
|
||||
|
||||
return { insert, update };
|
||||
|
|
Loading…
Reference in New Issue