Keyan b672d015e2
territory specific trust (#1965)
* territory specific trust

* functional parity with master

* revert back to materialized view for ranking

* update query for populating subWeightedVotes

* fix anon hot comments

* fix zap denormalization, change weightedComments to be for zaps, order updates of ancestors to prevent deadlocks

* reduce weight of comment zaps for hot score

* do zap ancestor updates together

* initialize trust in new/unpopular territories

* simplify denormalization of zap/downzaps

* recompute all scores
2025-03-15 08:11:33 -05:00

110 lines
5.6 KiB
SQL

-- AlterTable
ALTER TABLE "Item" ADD COLUMN "subWeightedDownVotes" FLOAT NOT NULL DEFAULT 0,
ADD COLUMN "subWeightedVotes" FLOAT NOT NULL DEFAULT 0;
CREATE INDEX "Item.sumSubVotes_index" ON "Item"(("subWeightedVotes" - "subWeightedDownVotes"));
-- CreateTable
CREATE TABLE "UserSubTrust" (
"subName" CITEXT NOT NULL,
"userId" INTEGER NOT NULL,
"zapPostTrust" DOUBLE PRECISION NOT NULL DEFAULT 0,
"subZapPostTrust" DOUBLE PRECISION NOT NULL DEFAULT 0,
"zapCommentTrust" DOUBLE PRECISION NOT NULL DEFAULT 0,
"subZapCommentTrust" DOUBLE PRECISION NOT NULL DEFAULT 0,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "UserSubTrust_pkey" PRIMARY KEY ("userId","subName")
);
-- AddForeignKey
ALTER TABLE "UserSubTrust" ADD CONSTRAINT "UserSubTrust_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "UserSubTrust" ADD CONSTRAINT "UserSubTrust_subName_fkey" FOREIGN KEY ("subName") REFERENCES "Sub"("name") ON DELETE CASCADE ON UPDATE CASCADE;
-- UserSubTrust is NOT populated, so this is a no-op ... but useful having it written out for migrating manually on deployment
UPDATE "Item"
SET "subWeightedVotes" = subquery."subWeightedVotes",
"subWeightedDownVotes" = subquery."subWeightedDownVotes",
"weightedVotes" = subquery."weightedVotes",
"weightedDownVotes" = subquery."weightedDownVotes"
FROM (
WITH sub_votes AS (
SELECT "ItemAct"."itemId",
CASE WHEN (SUM("ItemAct"."msats") FILTER (WHERE "ItemAct"."act" IN ('TIP', 'FEE')))::FLOAT > 0
THEN COALESCE(
LOG(
(SUM("ItemAct"."msats") FILTER (WHERE "ItemAct"."act" IN ('TIP', 'FEE')))::FLOAT / 1000
) * CASE
WHEN "Item"."parentId" IS NULL
THEN "UserSubTrust"."subZapPostTrust"
ELSE "UserSubTrust"."subZapCommentTrust"
END, 0)
ELSE 0
END AS "subWeightedVotes",
CASE WHEN (SUM("ItemAct"."msats") FILTER (WHERE "ItemAct"."act" IN ('TIP', 'FEE')))::FLOAT > 0
THEN COALESCE(
LOG(
(SUM("ItemAct"."msats") FILTER (WHERE "ItemAct"."act" IN ('TIP', 'FEE')))::FLOAT / 1000
) * CASE
WHEN "Item"."parentId" IS NULL
THEN "UserSubTrust"."zapPostTrust"
ELSE "UserSubTrust"."zapCommentTrust"
END, 0)
ELSE 0
END AS "weightedVotes",
CASE WHEN (SUM("ItemAct"."msats") FILTER (WHERE "ItemAct"."act" IN ('DONT_LIKE_THIS')))::FLOAT > 0
THEN COALESCE(
LOG(
(SUM("ItemAct"."msats") FILTER (WHERE "ItemAct"."act" IN ('DONT_LIKE_THIS')))::FLOAT / 1000
) * CASE
WHEN "Item"."parentId" IS NULL
THEN "UserSubTrust"."subZapPostTrust"
ELSE "UserSubTrust"."subZapCommentTrust"
END, 0)
ELSE 0
END AS "subWeightedDownVotes",
CASE WHEN (SUM("ItemAct"."msats") FILTER (WHERE "ItemAct"."act" IN ('DONT_LIKE_THIS')))::FLOAT > 0
THEN COALESCE(
LOG(
(SUM("ItemAct"."msats") FILTER (WHERE "ItemAct"."act" IN ('DONT_LIKE_THIS')))::FLOAT / 1000
) * CASE
WHEN "Item"."parentId" IS NULL
THEN "UserSubTrust"."zapPostTrust"
ELSE "UserSubTrust"."zapCommentTrust"
END, 0)
ELSE 0
END AS "weightedDownVotes"
FROM "ItemAct"
JOIN "UserSubTrust" ON "ItemAct"."userId" = "UserSubTrust"."userId"
JOIN "Item" ON "Item".id = "ItemAct"."itemId"
AND "UserSubTrust"."subName" = "Item"."subName"
AND "Item"."userId" <> "ItemAct"."userId"
WHERE "ItemAct".act IN ('TIP', 'FEE', 'DONT_LIKE_THIS')
GROUP BY "ItemAct"."itemId", "ItemAct"."userId", "UserSubTrust"."subZapPostTrust",
"UserSubTrust"."subZapCommentTrust", "UserSubTrust"."zapPostTrust", "UserSubTrust"."zapCommentTrust",
"Item"."parentId"
)
SELECT "itemId", SUM("subWeightedVotes") AS "subWeightedVotes", SUM("subWeightedDownVotes") AS "subWeightedDownVotes",
SUM("weightedVotes") AS "weightedVotes", SUM("weightedDownVotes") AS "weightedDownVotes"
FROM sub_votes
GROUP BY "itemId"
) AS subquery
WHERE "Item".id = subquery."itemId";
CREATE MATERIALIZED VIEW IF NOT EXISTS hot_score_view AS
SELECT id,
("Item"."weightedVotes" - "Item"."weightedDownVotes" + ("Item"."weightedComments"*0.25) + ("Item".boost / 5000))
/ POWER(GREATEST(3, EXTRACT(EPOCH FROM (now() - "Item".created_at))/3600), 1.1) AS hot_score,
("Item"."subWeightedVotes" - "Item"."subWeightedDownVotes" + ("Item"."weightedComments"*0.25) + ("Item".boost / 5000))
/ POWER(GREATEST(3, EXTRACT(EPOCH FROM (now() - "Item".created_at))/3600), 1.1) AS sub_hot_score
FROM "Item"
WHERE "Item"."weightedVotes" > 0 OR "Item"."weightedDownVotes" > 0 OR "Item"."subWeightedVotes" > 0
OR "Item"."subWeightedDownVotes" > 0 OR "Item"."weightedComments" > 0 OR "Item".boost > 0;
CREATE UNIQUE INDEX IF NOT EXISTS hot_score_view_id_idx ON hot_score_view(id);
CREATE INDEX IF NOT EXISTS hot_score_view_hot_score_idx ON hot_score_view(hot_score DESC NULLS LAST);
CREATE INDEX IF NOT EXISTS hot_score_view_sub_hot_score_idx ON hot_score_view(sub_hot_score DESC NULLS LAST);