diff --git a/package-lock.json b/package-lock.json index 8bf0c21..128eb0e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { "name": "traxxx-web", - "version": "0.25.5", + "version": "0.25.7", "lockfileVersion": 2, "requires": true, "packages": { "": { - "version": "0.25.5", + "version": "0.25.7", "dependencies": { "@brillout/json-serializer": "^0.5.8", "@dicebear/collection": "^7.0.5", diff --git a/package.json b/package.json index 47faee3..a20e5e6 100644 --- a/package.json +++ b/package.json @@ -78,5 +78,5 @@ "postcss-custom-media": "^10.0.2", "postcss-nesting": "^12.0.2" }, - "version": "0.25.5" + "version": "0.25.7" } diff --git a/pages/search/+Page.vue b/pages/search/+Page.vue index 87bd1f9..33dac13 100644 --- a/pages/search/+Page.vue +++ b/pages/search/+Page.vue @@ -105,6 +105,7 @@ const query = pageContext.urlParsed.search.q; .page { display: flex; flex-direction: column; + flex-grow: 1; } .row { diff --git a/src/movies.js b/src/movies.js index 7d10f16..d2d1920 100644 --- a/src/movies.js +++ b/src/movies.js @@ -8,6 +8,7 @@ import { curateMedia } from './media.js'; import { fetchTagsById } from './tags.js'; import { fetchEntitiesById } from './entities.js'; import { curateStash } from './stashes.js'; +import escape from '../utils/escape-manticore.js'; import promiseProps from '../utils/promise-props.js'; function curateMovie(rawMovie, assets) { @@ -171,179 +172,6 @@ function curateOptions(options) { }; } -/* -function buildQuery(filters = {}) { - const query = { - bool: { - must: [], - }, - }; - - let sort = [{ effective_date: 'desc' }]; - - if (!filters.scope || filters.scope === 'latest') { - query.bool.must.push({ - range: { - effective_date: { - lte: Math.round(Date.now() / 1000), - }, - }, - }); - } - - if (filters.scope === 'upcoming') { - query.bool.must.push({ - range: { - effective_date: { - gt: Math.round(Date.now() / 1000), - }, - }, - }); - - sort = [{ effective_date: 'asc' }]; - } - - if (filters.scope === 'new') { - sort = [{ created_at: 'desc' }, { effective_date: 'asc' }]; - } - - if (filters.scope === 'likes') { - sort = [{ stashed: 'desc' }, { effective_date: 'desc' }]; - } - - if (filters.scope === 'results') { - sort = [{ _score: 'desc' }, { effective_date: 'desc' }]; - } - - if (filters.query) { - query.bool.must.push({ - bool: { - should: [ - { match: { title_filtered: filters.query } }, - { match: { actors: filters.query } }, - { match: { tags: filters.query } }, - { match: { channel_name: filters.query } }, - { match: { network_name: filters.query } }, - { match: { channel_slug: filters.query } }, - { match: { network_slug: filters.query } }, - { match: { meta: filters.query } }, // date - ], - }, - }); - } - - if (filters.tagIds) { - filters.tagIds.forEach((tagId) => { - query.bool.must.push({ equals: { 'any(tag_ids)': tagId } }); - }); - } - - if (filters.entityId) { - query.bool.must.push({ - bool: { - should: [ - { equals: { channel_id: filters.entityId } }, - { equals: { network_id: filters.entityId } }, - ], - }, - }); - } - - if (filters.actorIds) { - filters.actorIds.forEach((actorId) => { - query.bool.must.push({ equals: { 'any(actor_ids)': actorId } }); - }); - } - - if (filters.requireCover) { - query.bool.must.push({ - equals: { - has_cover: 1, - }, - }); - } - - return { query, sort }; -} - -function buildAggregates(options) { - const aggregates = {}; - - if (options.aggregateActors) { - aggregates.actorIds = { - terms: { - field: 'actor_ids', - size: config.database.manticore.maxAggregateSize, - }, - // sort: [{ 'count(*)': { order: 'desc' } }], - }; - } - - if (options.aggregateTags) { - aggregates.tagIds = { - terms: { - field: 'tag_ids', - size: config.database.manticore.maxAggregateSize, - }, - }; - } - - if (options.aggregateChannels) { - aggregates.channelIds = { - terms: { - field: 'channel_id', - size: config.database.manticore.maxAggregateSize, - }, - }; - } - - return aggregates; -} - -async function queryManticoreJson(filters, options) { - const { query, sort } = buildQuery(filters); - - console.log('query', query.bool.must); - - console.time('manticore'); - - const result = await searchApi.search({ - index: 'movies', - query, - limit: options.limit, - offset: (options.page - 1) * options.limit, - sort, - aggs: buildAggregates(options), - options: { - max_matches: config.database.manticore.maxMatches, - max_query_time: config.database.manticore.maxQueryTime, - field_weights: { - title_filtered: 7, - actors: 10, - tags: 9, - meta: 6, - channel_name: 2, - channel_slug: 3, - network_name: 1, - network_slug: 1, - }, - }, - }); - - const movies = result.hits.hits.map((hit) => ({ - id: hit._id, - ...hit._source, - _score: hit._score, - })); - - return { - movies, - total: result.hits.total, - aggregations: result.aggregations && Object.fromEntries(Object.entries(result.aggregations).map(([key, { buckets }]) => [key, buckets])), - }; -} -*/ - async function queryManticoreSql(filters, options) { const aggSize = config.database.manticore.maxAggregateSize; @@ -393,7 +221,7 @@ async function queryManticoreSql(filters, options) { } if (filters.query) { - builder.whereRaw('match(\'@!title :query:\', movies)', { query: filters.query }); + builder.whereRaw('match(\'@!title :query:\', movies)', { query: escape(filters.query) }); } filters.tagIds?.forEach((tagId) => { diff --git a/src/web/graphql.js b/src/web/graphql.js new file mode 100644 index 0000000..ccae6b6 --- /dev/null +++ b/src/web/graphql.js @@ -0,0 +1,27 @@ +import { graphql, buildSchema } from 'graphql'; +import { scenesSchema, fetchScenesGraphql } from './scenes.js'; + +const schema = buildSchema(` + type Query { + scenes: [Scene] + } + + ${scenesSchema} +`); + +const rootValue = { + scenes: fetchScenesGraphql, +}; + +export async function graphqlApi(req, res) { + const data = await graphql({ + schema, + source: req.body.query, + variableValues: req.body.variables, + rootValue, + }); + + console.log(data); + + res.send(data); +}