preserve ordering in new layered item query

This commit is contained in:
keyan 2023-05-08 15:06:42 -05:00
parent 01d29e013e
commit 67b815d9d6

View File

@ -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 `