preserve ordering in new layered item query
This commit is contained in:
parent
01d29e013e
commit
67b815d9d6
@ -40,10 +40,14 @@ async function comments (me, models, id, sort) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function getItem (parent, { id }, { me, models }) {
|
export async function getItem (parent, { id }, { me, models }) {
|
||||||
const [item] = await itemQueryWithMeta(me, models, `
|
const [item] = await itemQueryWithMeta({
|
||||||
${SELECT}
|
me,
|
||||||
FROM "Item"
|
models,
|
||||||
WHERE id = $1`, Number(id))
|
query: `
|
||||||
|
${SELECT}
|
||||||
|
FROM "Item"
|
||||||
|
WHERE id = $1`
|
||||||
|
}, Number(id))
|
||||||
return item
|
return item
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,15 +147,17 @@ function recentClause (type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this grabs all the stuff we need to display the item list and only
|
// this grabs all the stuff we need to display the item list and only
|
||||||
// hits the db once
|
// hits the db once ... orderBy needs to be duplicated on the outer query because
|
||||||
async function itemQueryWithMeta (me, models, query, ...args) {
|
// joining does not preserve the order of the inner query
|
||||||
|
async function itemQueryWithMeta ({ me, models, query, orderBy = '' }, ...args) {
|
||||||
if (!me) {
|
if (!me) {
|
||||||
return await models.$queryRaw(`
|
return await models.$queryRaw(`
|
||||||
SELECT "Item".*, to_json(users.*) as user
|
SELECT "Item".*, to_json(users.*) as user
|
||||||
FROM (
|
FROM (
|
||||||
${query}
|
${query}
|
||||||
) "Item"
|
) "Item"
|
||||||
JOIN users ON "Item"."userId" = users.id`, ...args)
|
JOIN users ON "Item"."userId" = users.id
|
||||||
|
${orderBy}`, ...args)
|
||||||
} else {
|
} else {
|
||||||
return await models.$queryRaw(`
|
return await models.$queryRaw(`
|
||||||
SELECT "Item".*, to_json(users.*) as user, COALESCE("ItemAct"."meMsats", 0) as "meMsats",
|
SELECT "Item".*, to_json(users.*) as user, COALESCE("ItemAct"."meMsats", 0) as "meMsats",
|
||||||
@ -168,7 +174,8 @@ async function itemQueryWithMeta (me, models, query, ...args) {
|
|||||||
WHERE "ItemAct"."userId" = ${me.id}
|
WHERE "ItemAct"."userId" = ${me.id}
|
||||||
AND "ItemAct"."itemId" = "Item".id
|
AND "ItemAct"."itemId" = "Item".id
|
||||||
GROUP BY "ItemAct"."itemId"
|
GROUP BY "ItemAct"."itemId"
|
||||||
) "ItemAct" ON true`, ...args)
|
) "ItemAct" ON true
|
||||||
|
${orderBy}`, ...args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,16 +195,21 @@ export default {
|
|||||||
},
|
},
|
||||||
topItems: async (parent, { cursor, sort, when }, { me, models }) => {
|
topItems: async (parent, { cursor, sort, when }, { me, models }) => {
|
||||||
const decodedCursor = decodeCursor(cursor)
|
const decodedCursor = decodeCursor(cursor)
|
||||||
const items = await itemQueryWithMeta(me, models, `
|
const items = await itemQueryWithMeta({
|
||||||
${SELECT}
|
me,
|
||||||
FROM "Item"
|
models,
|
||||||
WHERE "parentId" IS NULL AND "Item".created_at <= $1
|
query: `
|
||||||
AND "pinId" IS NULL AND "deletedAt" IS NULL
|
${SELECT}
|
||||||
${topClause(when)}
|
FROM "Item"
|
||||||
${await filterClause(me, models)}
|
WHERE "parentId" IS NULL AND "Item".created_at <= $1
|
||||||
${await topOrderClause(sort, me, models)}
|
AND "pinId" IS NULL AND "deletedAt" IS NULL
|
||||||
OFFSET $2
|
${topClause(when)}
|
||||||
LIMIT ${LIMIT}`, decodedCursor.time, decodedCursor.offset)
|
${await filterClause(me, models)}
|
||||||
|
${await topOrderClause(sort, me, models)}
|
||||||
|
OFFSET $2
|
||||||
|
LIMIT ${LIMIT}`,
|
||||||
|
orderBy: await topOrderClause(sort, me, models)
|
||||||
|
}, decodedCursor.time, decodedCursor.offset)
|
||||||
return {
|
return {
|
||||||
cursor: items.length === LIMIT ? nextCursorEncoded(decodedCursor) : null,
|
cursor: items.length === LIMIT ? nextCursorEncoded(decodedCursor) : null,
|
||||||
items
|
items
|
||||||
@ -205,16 +217,21 @@ export default {
|
|||||||
},
|
},
|
||||||
topComments: async (parent, { cursor, sort, when }, { me, models }) => {
|
topComments: async (parent, { cursor, sort, when }, { me, models }) => {
|
||||||
const decodedCursor = decodeCursor(cursor)
|
const decodedCursor = decodeCursor(cursor)
|
||||||
const comments = await itemQueryWithMeta(me, models, `
|
const comments = await itemQueryWithMeta({
|
||||||
${SELECT}
|
me,
|
||||||
FROM "Item"
|
models,
|
||||||
WHERE "parentId" IS NOT NULL
|
query: `
|
||||||
AND "Item".created_at <= $1 AND "deletedAt" IS NULL
|
${SELECT}
|
||||||
${topClause(when)}
|
FROM "Item"
|
||||||
${await filterClause(me, models)}
|
WHERE "parentId" IS NOT NULL
|
||||||
${await topOrderClause(sort, me, models)}
|
AND "Item".created_at <= $1 AND "deletedAt" IS NULL
|
||||||
OFFSET $2
|
${topClause(when)}
|
||||||
LIMIT ${LIMIT}`, decodedCursor.time, decodedCursor.offset)
|
${await filterClause(me, models)}
|
||||||
|
${await topOrderClause(sort, me, models)}
|
||||||
|
OFFSET $2
|
||||||
|
LIMIT ${LIMIT}`,
|
||||||
|
orderBy: await topOrderClause(sort, me, models)
|
||||||
|
}, decodedCursor.time, decodedCursor.offset)
|
||||||
return {
|
return {
|
||||||
cursor: comments.length === LIMIT ? nextCursorEncoded(decodedCursor) : null,
|
cursor: comments.length === LIMIT ? nextCursorEncoded(decodedCursor) : null,
|
||||||
comments
|
comments
|
||||||
@ -243,41 +260,56 @@ export default {
|
|||||||
throw new UserInputError('no user has that name', { argumentName: 'name' })
|
throw new UserInputError('no user has that name', { argumentName: 'name' })
|
||||||
}
|
}
|
||||||
|
|
||||||
items = await itemQueryWithMeta(me, models, `
|
items = await itemQueryWithMeta({
|
||||||
${SELECT}
|
me,
|
||||||
FROM "Item"
|
models,
|
||||||
WHERE "userId" = $1 AND "parentId" IS NULL AND created_at <= $2
|
query: `
|
||||||
AND "pinId" IS NULL
|
${SELECT}
|
||||||
${activeOrMine()}
|
FROM "Item"
|
||||||
${await filterClause(me, models)}
|
WHERE "userId" = $1 AND "parentId" IS NULL AND created_at <= $2
|
||||||
ORDER BY created_at DESC
|
AND "pinId" IS NULL
|
||||||
OFFSET $3
|
${activeOrMine()}
|
||||||
LIMIT ${LIMIT}`, user.id, decodedCursor.time, decodedCursor.offset)
|
${await filterClause(me, models)}
|
||||||
|
ORDER BY created_at DESC
|
||||||
|
OFFSET $3
|
||||||
|
LIMIT ${LIMIT}`,
|
||||||
|
orderBy: 'ORDER BY "Item"."createdAt" DESC'
|
||||||
|
}, user.id, decodedCursor.time, decodedCursor.offset)
|
||||||
break
|
break
|
||||||
case 'recent':
|
case 'recent':
|
||||||
items = await itemQueryWithMeta(me, models, `
|
items = await itemQueryWithMeta({
|
||||||
${SELECT}
|
me,
|
||||||
FROM "Item"
|
models,
|
||||||
WHERE "parentId" IS NULL AND created_at <= $1
|
query: `
|
||||||
${subClause(sub, 3)}
|
${SELECT}
|
||||||
${activeOrMine()}
|
FROM "Item"
|
||||||
${await filterClause(me, models)}
|
WHERE "parentId" IS NULL AND created_at <= $1
|
||||||
${recentClause(type)}
|
${subClause(sub, 3)}
|
||||||
ORDER BY created_at DESC
|
${activeOrMine()}
|
||||||
OFFSET $2
|
${await filterClause(me, models)}
|
||||||
LIMIT ${LIMIT}`, decodedCursor.time, decodedCursor.offset, ...subArr)
|
${recentClause(type)}
|
||||||
|
ORDER BY created_at DESC
|
||||||
|
OFFSET $2
|
||||||
|
LIMIT ${LIMIT}`,
|
||||||
|
orderBy: 'ORDER BY "Item"."createdAt" DESC'
|
||||||
|
}, decodedCursor.time, decodedCursor.offset, ...subArr)
|
||||||
break
|
break
|
||||||
case 'top':
|
case 'top':
|
||||||
items = await itemQueryWithMeta(me, models, `
|
items = await itemQueryWithMeta({
|
||||||
${SELECT}
|
me,
|
||||||
FROM "Item"
|
models,
|
||||||
WHERE "parentId" IS NULL AND "Item".created_at <= $1
|
query: `
|
||||||
AND "pinId" IS NULL AND "deletedAt" IS NULL
|
${SELECT}
|
||||||
${topClause(within)}
|
FROM "Item"
|
||||||
${await filterClause(me, models)}
|
WHERE "parentId" IS NULL AND "Item".created_at <= $1
|
||||||
${await topOrderByWeightedSats(me, models)}
|
AND "pinId" IS NULL AND "deletedAt" IS NULL
|
||||||
OFFSET $2
|
${topClause(within)}
|
||||||
LIMIT ${LIMIT}`, decodedCursor.time, decodedCursor.offset)
|
${await filterClause(me, models)}
|
||||||
|
${await topOrderByWeightedSats(me, models)}
|
||||||
|
OFFSET $2
|
||||||
|
LIMIT ${LIMIT}`,
|
||||||
|
orderBy: await topOrderByWeightedSats(me, models)
|
||||||
|
}, decodedCursor.time, decodedCursor.offset)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
// sub so we know the default ranking
|
// sub so we know the default ranking
|
||||||
@ -287,27 +319,31 @@ export default {
|
|||||||
|
|
||||||
switch (subFull?.rankingType) {
|
switch (subFull?.rankingType) {
|
||||||
case 'AUCTION':
|
case 'AUCTION':
|
||||||
items = await itemQueryWithMeta(me, models, `
|
items = await itemQueryWithMeta({
|
||||||
SELECT *
|
me,
|
||||||
FROM (
|
models,
|
||||||
(${SELECT}
|
query: `
|
||||||
FROM "Item"
|
SELECT *
|
||||||
WHERE "parentId" IS NULL AND created_at <= $1
|
FROM (
|
||||||
AND "pinId" IS NULL
|
(${SELECT}
|
||||||
${subClause(sub, 3)}
|
FROM "Item"
|
||||||
AND status = 'ACTIVE' AND "maxBid" > 0
|
WHERE "parentId" IS NULL AND created_at <= $1
|
||||||
ORDER BY "maxBid" DESC, created_at ASC)
|
AND "pinId" IS NULL
|
||||||
UNION ALL
|
${subClause(sub, 3)}
|
||||||
(${SELECT}
|
AND status = 'ACTIVE' AND "maxBid" > 0
|
||||||
FROM "Item"
|
ORDER BY "maxBid" DESC, created_at ASC)
|
||||||
WHERE "parentId" IS NULL AND created_at <= $1
|
UNION ALL
|
||||||
AND "pinId" IS NULL
|
(${SELECT}
|
||||||
${subClause(sub, 3)}
|
FROM "Item"
|
||||||
AND ((status = 'ACTIVE' AND "maxBid" = 0) OR status = 'NOSATS')
|
WHERE "parentId" IS NULL AND created_at <= $1
|
||||||
ORDER BY created_at DESC)
|
AND "pinId" IS NULL
|
||||||
) a
|
${subClause(sub, 3)}
|
||||||
OFFSET $2
|
AND ((status = 'ACTIVE' AND "maxBid" = 0) OR status = 'NOSATS')
|
||||||
LIMIT ${LIMIT}`, decodedCursor.time, decodedCursor.offset, ...subArr)
|
ORDER BY created_at DESC)
|
||||||
|
) a
|
||||||
|
OFFSET $2
|
||||||
|
LIMIT ${LIMIT}`
|
||||||
|
}, decodedCursor.time, decodedCursor.offset, ...subArr)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
// HACK we can speed hack the first hot page, by limiting our query to only
|
// HACK we can speed hack the first hot page, by limiting our query to only
|
||||||
@ -317,7 +353,10 @@ export default {
|
|||||||
// if there are 21 items, return them ... if not do the unrestricted query
|
// if there are 21 items, return them ... if not do the unrestricted query
|
||||||
// instead of doing this we should materialize a view ... but this is easier for now
|
// instead of doing this we should materialize a view ... but this is easier for now
|
||||||
if (decodedCursor.offset === 0) {
|
if (decodedCursor.offset === 0) {
|
||||||
items = await itemQueryWithMeta(me, models, `
|
items = await itemQueryWithMeta({
|
||||||
|
me,
|
||||||
|
models,
|
||||||
|
query: `
|
||||||
${SELECT}
|
${SELECT}
|
||||||
FROM "Item"
|
FROM "Item"
|
||||||
WHERE "parentId" IS NULL AND "Item".created_at <= $1 AND "Item".created_at > $3
|
WHERE "parentId" IS NULL AND "Item".created_at <= $1 AND "Item".created_at > $3
|
||||||
@ -326,11 +365,16 @@ export default {
|
|||||||
${await filterClause(me, models)}
|
${await filterClause(me, models)}
|
||||||
${await newTimedOrderByWeightedSats(me, models, 1)}
|
${await newTimedOrderByWeightedSats(me, models, 1)}
|
||||||
OFFSET $2
|
OFFSET $2
|
||||||
LIMIT ${LIMIT}`, decodedCursor.time, decodedCursor.offset, new Date(new Date().setDate(new Date().getDate() - 5)), ...subArr)
|
LIMIT ${LIMIT}`,
|
||||||
|
orderBy: await newTimedOrderByWeightedSats(me, models, 1)
|
||||||
|
}, decodedCursor.time, decodedCursor.offset, new Date(new Date().setDate(new Date().getDate() - 5)), ...subArr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decodedCursor.offset !== 0 || items?.length < LIMIT) {
|
if (decodedCursor.offset !== 0 || items?.length < LIMIT) {
|
||||||
items = await itemQueryWithMeta(me, models, `
|
items = await itemQueryWithMeta({
|
||||||
|
me,
|
||||||
|
models,
|
||||||
|
query: `
|
||||||
${SELECT}
|
${SELECT}
|
||||||
FROM "Item"
|
FROM "Item"
|
||||||
WHERE "parentId" IS NULL AND "Item".created_at <= $1
|
WHERE "parentId" IS NULL AND "Item".created_at <= $1
|
||||||
@ -339,22 +383,29 @@ export default {
|
|||||||
${await filterClause(me, models)}
|
${await filterClause(me, models)}
|
||||||
${await newTimedOrderByWeightedSats(me, models, 1)}
|
${await newTimedOrderByWeightedSats(me, models, 1)}
|
||||||
OFFSET $2
|
OFFSET $2
|
||||||
LIMIT ${LIMIT}`, decodedCursor.time, decodedCursor.offset, ...subArr)
|
LIMIT ${LIMIT}`,
|
||||||
|
orderBy: await newTimedOrderByWeightedSats(me, models, 1)
|
||||||
|
}, decodedCursor.time, decodedCursor.offset, ...subArr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decodedCursor.offset === 0) {
|
if (decodedCursor.offset === 0) {
|
||||||
// get pins for the page and return those separately
|
// get pins for the page and return those separately
|
||||||
pins = await itemQueryWithMeta(me, models, `SELECT rank_filter.*
|
pins = await itemQueryWithMeta({
|
||||||
FROM (
|
me,
|
||||||
${SELECT},
|
models,
|
||||||
rank() OVER (
|
query: `
|
||||||
PARTITION BY "pinId"
|
SELECT rank_filter.*
|
||||||
ORDER BY created_at DESC
|
FROM (
|
||||||
)
|
${SELECT},
|
||||||
FROM "Item"
|
rank() OVER (
|
||||||
WHERE "pinId" IS NOT NULL
|
PARTITION BY "pinId"
|
||||||
${subClause(sub, 1)}
|
ORDER BY created_at DESC
|
||||||
) rank_filter WHERE RANK = 1`, ...subArr)
|
)
|
||||||
|
FROM "Item"
|
||||||
|
WHERE "pinId" IS NOT NULL
|
||||||
|
${subClause(sub, 1)}
|
||||||
|
) rank_filter WHERE RANK = 1`
|
||||||
|
}, ...subArr)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -368,12 +419,17 @@ export default {
|
|||||||
},
|
},
|
||||||
allItems: async (parent, { cursor }, { me, models }) => {
|
allItems: async (parent, { cursor }, { me, models }) => {
|
||||||
const decodedCursor = decodeCursor(cursor)
|
const decodedCursor = decodeCursor(cursor)
|
||||||
const items = await itemQueryWithMeta(me, models, `
|
const items = await itemQueryWithMeta({
|
||||||
${SELECT}
|
me,
|
||||||
FROM "Item"
|
models,
|
||||||
ORDER BY created_at DESC
|
query: `
|
||||||
OFFSET $1
|
${SELECT}
|
||||||
LIMIT ${LIMIT}`, decodedCursor.offset)
|
FROM "Item"
|
||||||
|
ORDER BY created_at DESC
|
||||||
|
OFFSET $1
|
||||||
|
LIMIT ${LIMIT}`,
|
||||||
|
orderBy: 'ORDER BY "Item"."createdAt" DESC'
|
||||||
|
}, decodedCursor.offset)
|
||||||
return {
|
return {
|
||||||
cursor: items.length === LIMIT ? nextCursorEncoded(decodedCursor) : null,
|
cursor: items.length === LIMIT ? nextCursorEncoded(decodedCursor) : null,
|
||||||
items
|
items
|
||||||
@ -385,14 +441,19 @@ export default {
|
|||||||
return me ? ` AND "userId" <> ${me.id} ` : ''
|
return me ? ` AND "userId" <> ${me.id} ` : ''
|
||||||
}
|
}
|
||||||
|
|
||||||
const items = await itemQueryWithMeta(me, models, `
|
const items = await itemQueryWithMeta({
|
||||||
${SELECT}
|
me,
|
||||||
FROM "Item"
|
models,
|
||||||
WHERE "Item"."weightedVotes" - "Item"."weightedDownVotes" <= -${ITEM_FILTER_THRESHOLD}
|
query: `
|
||||||
${notMine()}
|
${SELECT}
|
||||||
ORDER BY created_at DESC
|
FROM "Item"
|
||||||
OFFSET $1
|
WHERE "Item"."weightedVotes" - "Item"."weightedDownVotes" <= -${ITEM_FILTER_THRESHOLD}
|
||||||
LIMIT ${LIMIT}`, decodedCursor.offset)
|
${notMine()}
|
||||||
|
ORDER BY created_at DESC
|
||||||
|
OFFSET $1
|
||||||
|
LIMIT ${LIMIT}`,
|
||||||
|
orderBy: 'ORDER BY "Item"."createdAt" DESC'
|
||||||
|
}, decodedCursor.offset)
|
||||||
return {
|
return {
|
||||||
cursor: items.length === LIMIT ? nextCursorEncoded(decodedCursor) : null,
|
cursor: items.length === LIMIT ? nextCursorEncoded(decodedCursor) : null,
|
||||||
items
|
items
|
||||||
@ -404,15 +465,20 @@ export default {
|
|||||||
return me ? ` AND "userId" <> ${me.id} ` : ''
|
return me ? ` AND "userId" <> ${me.id} ` : ''
|
||||||
}
|
}
|
||||||
|
|
||||||
const items = await itemQueryWithMeta(me, models, `
|
const items = await itemQueryWithMeta({
|
||||||
${SELECT}
|
me,
|
||||||
FROM "Item"
|
models,
|
||||||
WHERE "Item"."weightedVotes" - "Item"."weightedDownVotes" < 0
|
query: `
|
||||||
AND "Item"."weightedVotes" - "Item"."weightedDownVotes" > -${ITEM_FILTER_THRESHOLD}
|
${SELECT}
|
||||||
${notMine()}
|
FROM "Item"
|
||||||
ORDER BY created_at DESC
|
WHERE "Item"."weightedVotes" - "Item"."weightedDownVotes" < 0
|
||||||
OFFSET $1
|
AND "Item"."weightedVotes" - "Item"."weightedDownVotes" > -${ITEM_FILTER_THRESHOLD}
|
||||||
LIMIT ${LIMIT}`, decodedCursor.offset)
|
${notMine()}
|
||||||
|
ORDER BY created_at DESC
|
||||||
|
OFFSET $1
|
||||||
|
LIMIT ${LIMIT}`,
|
||||||
|
orderBy: 'ORDER BY "Item"."createdAt" DESC'
|
||||||
|
}, decodedCursor.offset)
|
||||||
return {
|
return {
|
||||||
cursor: items.length === LIMIT ? nextCursorEncoded(decodedCursor) : null,
|
cursor: items.length === LIMIT ? nextCursorEncoded(decodedCursor) : null,
|
||||||
items
|
items
|
||||||
@ -421,13 +487,18 @@ export default {
|
|||||||
freebieItems: async (parent, { cursor }, { me, models }) => {
|
freebieItems: async (parent, { cursor }, { me, models }) => {
|
||||||
const decodedCursor = decodeCursor(cursor)
|
const decodedCursor = decodeCursor(cursor)
|
||||||
|
|
||||||
const items = await itemQueryWithMeta(me, models, `
|
const items = await itemQueryWithMeta({
|
||||||
${SELECT}
|
me,
|
||||||
FROM "Item"
|
models,
|
||||||
WHERE "Item".freebie
|
query: `
|
||||||
ORDER BY created_at DESC
|
${SELECT}
|
||||||
OFFSET $1
|
FROM "Item"
|
||||||
LIMIT ${LIMIT}`, decodedCursor.offset)
|
WHERE "Item".freebie
|
||||||
|
ORDER BY created_at DESC
|
||||||
|
OFFSET $1
|
||||||
|
LIMIT ${LIMIT}`,
|
||||||
|
orderBy: 'ORDER BY "Item"."createdAt" DESC'
|
||||||
|
}, decodedCursor.offset)
|
||||||
return {
|
return {
|
||||||
cursor: items.length === LIMIT ? nextCursorEncoded(decodedCursor) : null,
|
cursor: items.length === LIMIT ? nextCursorEncoded(decodedCursor) : null,
|
||||||
items
|
items
|
||||||
@ -443,14 +514,19 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const items = await itemQueryWithMeta(me, models, `
|
const items = await itemQueryWithMeta({
|
||||||
${SELECT}
|
me,
|
||||||
FROM "Item"
|
models,
|
||||||
WHERE "userId" = $1
|
query: `
|
||||||
AND "bounty" IS NOT NULL
|
${SELECT}
|
||||||
ORDER BY created_at DESC
|
FROM "Item"
|
||||||
OFFSET $2
|
WHERE "userId" = $1
|
||||||
LIMIT $3`, user.id, decodedCursor.offset, limit || LIMIT)
|
AND "bounty" IS NOT NULL
|
||||||
|
ORDER BY created_at DESC
|
||||||
|
OFFSET $2
|
||||||
|
LIMIT $3`,
|
||||||
|
orderBy: 'ORDER BY "Item"."createdAt" DESC'
|
||||||
|
}, user.id, decodedCursor.offset, limit || LIMIT)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
cursor: items.length === (limit || LIMIT) ? nextCursorEncoded(decodedCursor) : null,
|
cursor: items.length === (limit || LIMIT) ? nextCursorEncoded(decodedCursor) : null,
|
||||||
@ -466,16 +542,21 @@ export default {
|
|||||||
let comments, user
|
let comments, user
|
||||||
switch (sort) {
|
switch (sort) {
|
||||||
case 'recent':
|
case 'recent':
|
||||||
comments = await itemQueryWithMeta(me, models, `
|
comments = await itemQueryWithMeta({
|
||||||
${SELECT}
|
me,
|
||||||
FROM "Item"
|
models,
|
||||||
JOIN "Item" root ON "Item"."rootId" = root.id
|
query: `
|
||||||
WHERE "Item"."parentId" IS NOT NULL AND "Item".created_at <= $1
|
${SELECT}
|
||||||
${subClause(sub, 3, 'root')}
|
FROM "Item"
|
||||||
${await filterClause(me, models)}
|
JOIN "Item" root ON "Item"."rootId" = root.id
|
||||||
ORDER BY "Item".created_at DESC
|
WHERE "Item"."parentId" IS NOT NULL AND "Item".created_at <= $1
|
||||||
OFFSET $2
|
${subClause(sub, 3, 'root')}
|
||||||
LIMIT ${LIMIT}`, decodedCursor.time, decodedCursor.offset, ...subArr)
|
${await filterClause(me, models)}
|
||||||
|
ORDER BY "Item".created_at DESC
|
||||||
|
OFFSET $2
|
||||||
|
LIMIT ${LIMIT}`,
|
||||||
|
orderBy: 'ORDER BY "Item"."createdAt" DESC'
|
||||||
|
}, decodedCursor.time, decodedCursor.offset, ...subArr)
|
||||||
break
|
break
|
||||||
case 'user':
|
case 'user':
|
||||||
if (!name) {
|
if (!name) {
|
||||||
@ -487,27 +568,37 @@ export default {
|
|||||||
throw new UserInputError('no user has that name', { argumentName: 'name' })
|
throw new UserInputError('no user has that name', { argumentName: 'name' })
|
||||||
}
|
}
|
||||||
|
|
||||||
comments = await itemQueryWithMeta(me, models, `
|
comments = await itemQueryWithMeta({
|
||||||
${SELECT}
|
me,
|
||||||
FROM "Item"
|
models,
|
||||||
WHERE "userId" = $1 AND "parentId" IS NOT NULL
|
query: `
|
||||||
AND created_at <= $2
|
${SELECT}
|
||||||
${await filterClause(me, models)}
|
FROM "Item"
|
||||||
ORDER BY created_at DESC
|
WHERE "userId" = $1 AND "parentId" IS NOT NULL
|
||||||
OFFSET $3
|
AND created_at <= $2
|
||||||
LIMIT ${LIMIT}`, user.id, decodedCursor.time, decodedCursor.offset)
|
${await filterClause(me, models)}
|
||||||
|
ORDER BY created_at DESC
|
||||||
|
OFFSET $3
|
||||||
|
LIMIT ${LIMIT}`,
|
||||||
|
orderBy: 'ORDER BY "Item"."createdAt" DESC'
|
||||||
|
}, user.id, decodedCursor.time, decodedCursor.offset)
|
||||||
break
|
break
|
||||||
case 'top':
|
case 'top':
|
||||||
comments = await itemQueryWithMeta(me, models, `
|
comments = await itemQueryWithMeta({
|
||||||
${SELECT}
|
me,
|
||||||
FROM "Item"
|
models,
|
||||||
WHERE "Item"."parentId" IS NOT NULL AND"Item"."deletedAt" IS NULL
|
query: `
|
||||||
AND "Item".created_at <= $1
|
${SELECT}
|
||||||
${topClause(within)}
|
FROM "Item"
|
||||||
${await filterClause(me, models)}
|
WHERE "Item"."parentId" IS NOT NULL AND"Item"."deletedAt" IS NULL
|
||||||
${await topOrderByWeightedSats(me, models)}
|
AND "Item".created_at <= $1
|
||||||
OFFSET $2
|
${topClause(within)}
|
||||||
LIMIT ${LIMIT}`, decodedCursor.time, decodedCursor.offset)
|
${await filterClause(me, models)}
|
||||||
|
${await topOrderByWeightedSats(me, models)}
|
||||||
|
OFFSET $2
|
||||||
|
LIMIT ${LIMIT}`,
|
||||||
|
orderBy: await topOrderByWeightedSats(me, models)
|
||||||
|
}, decodedCursor.time, decodedCursor.offset)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
throw new UserInputError('invalid sort type', { argumentName: 'sort' })
|
throw new UserInputError('invalid sort type', { argumentName: 'sort' })
|
||||||
@ -526,14 +617,19 @@ export default {
|
|||||||
throw new UserInputError('no user has that name', { argumentName: 'name' })
|
throw new UserInputError('no user has that name', { argumentName: 'name' })
|
||||||
}
|
}
|
||||||
|
|
||||||
const items = await itemQueryWithMeta(me, models, `
|
const items = await itemQueryWithMeta({
|
||||||
${SELECT}
|
me,
|
||||||
FROM "Item"
|
models,
|
||||||
JOIN "Bookmark" ON "Bookmark"."itemId" = "Item"."id" AND "Bookmark"."userId" = $1
|
query: `
|
||||||
AND "Bookmark".created_at <= $2
|
${SELECT}, "Bookmark".created_at as "bookmarkCreatedAt"
|
||||||
ORDER BY "Bookmark".created_at DESC
|
FROM "Item"
|
||||||
OFFSET $3
|
JOIN "Bookmark" ON "Bookmark"."itemId" = "Item"."id" AND "Bookmark"."userId" = $1
|
||||||
LIMIT ${LIMIT}`, user.id, decodedCursor.time, decodedCursor.offset)
|
AND "Bookmark".created_at <= $2
|
||||||
|
ORDER BY "Bookmark".created_at DESC
|
||||||
|
OFFSET $3
|
||||||
|
LIMIT ${LIMIT}`,
|
||||||
|
orderBy: 'ORDER BY "bookmarkCreatedAt" DESC'
|
||||||
|
}, user.id, decodedCursor.time, decodedCursor.offset)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
cursor: items.length === LIMIT ? nextCursorEncoded(decodedCursor) : null,
|
cursor: items.length === LIMIT ? nextCursorEncoded(decodedCursor) : null,
|
||||||
@ -586,12 +682,16 @@ export default {
|
|||||||
similar += '((\\?|#)%)?'
|
similar += '((\\?|#)%)?'
|
||||||
}
|
}
|
||||||
|
|
||||||
return await itemQueryWithMeta(me, models, `
|
return await itemQueryWithMeta({
|
||||||
${SELECT}
|
me,
|
||||||
FROM "Item"
|
models,
|
||||||
WHERE LOWER(url) SIMILAR TO LOWER($1)
|
query: `
|
||||||
ORDER BY created_at DESC
|
${SELECT}
|
||||||
LIMIT 3`, similar)
|
FROM "Item"
|
||||||
|
WHERE LOWER(url) SIMILAR TO LOWER($1)
|
||||||
|
ORDER BY created_at DESC
|
||||||
|
LIMIT 3`
|
||||||
|
}, similar)
|
||||||
},
|
},
|
||||||
comments: async (parent, { id, sort }, { me, models }) => {
|
comments: async (parent, { id, sort }, { me, models }) => {
|
||||||
return comments(me, models, id, sort)
|
return comments(me, models, id, sort)
|
||||||
@ -1144,13 +1244,14 @@ const createItem = async (parent, { sub, title, url, text, boost, forward, bount
|
|||||||
|
|
||||||
// we have to do our own query because ltree is unsupported
|
// we have to do our own query because ltree is unsupported
|
||||||
export const SELECT =
|
export const SELECT =
|
||||||
`SELECT "Item".id, "Item".created_at as "createdAt", "Item".updated_at as "updatedAt", "Item".title,
|
`SELECT "Item".id, "Item".created_at, "Item".created_at as "createdAt", "Item".updated_at,
|
||||||
"Item".text, "Item".url, "Item"."bounty", "Item"."userId", "Item"."fwdUserId", "Item"."parentId",
|
"Item".updated_at as "updatedAt", "Item".title, "Item".text, "Item".url, "Item"."bounty",
|
||||||
"Item"."pinId", "Item"."maxBid", "Item"."rootId", "Item".upvotes,
|
"Item"."userId", "Item"."fwdUserId", "Item"."parentId", "Item"."pinId", "Item"."maxBid",
|
||||||
"Item".company, "Item".location, "Item".remote, "Item"."deletedAt",
|
"Item"."rootId", "Item".upvotes, "Item".company, "Item".location, "Item".remote, "Item"."deletedAt",
|
||||||
"Item"."subName", "Item".status, "Item"."uploadId", "Item"."pollCost", "Item".boost,
|
"Item"."subName", "Item".status, "Item"."uploadId", "Item"."pollCost", "Item".boost, "Item".msats,
|
||||||
"Item".msats, "Item".ncomments, "Item"."commentMsats", "Item"."lastCommentAt", "Item"."weightedVotes",
|
"Item".ncomments, "Item"."commentMsats", "Item"."lastCommentAt", "Item"."weightedVotes",
|
||||||
"Item"."weightedDownVotes", "Item".freebie, "Item"."otsHash", "Item"."bountyPaidTo", ltree2text("Item"."path") AS "path"`
|
"Item"."weightedDownVotes", "Item".freebie, "Item"."otsHash", "Item"."bountyPaidTo",
|
||||||
|
ltree2text("Item"."path") AS "path"`
|
||||||
|
|
||||||
async function newTimedOrderByWeightedSats (me, models, num) {
|
async function newTimedOrderByWeightedSats (me, models, num) {
|
||||||
return `
|
return `
|
||||||
|
Loading…
x
Reference in New Issue
Block a user