Filter trade counts to the last 6 months
This commit is contained in:
parent
62952b80dd
commit
3984f9c9ba
2 changed files with 43 additions and 56 deletions
|
@ -535,55 +535,6 @@ const buildItemAllOccupiedZonesLoader = (db) =>
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const buildItemTradeCountsLoader = (db) =>
|
|
||||||
new DataLoader(
|
|
||||||
async (itemIdOwnedPairs) => {
|
|
||||||
const qs = itemIdOwnedPairs
|
|
||||||
.map((_) => "(closet_hangers.item_id = ? AND closet_hangers.owned = ?)")
|
|
||||||
.join(" OR ");
|
|
||||||
const values = itemIdOwnedPairs
|
|
||||||
.map(({ itemId, isOwned }) => [itemId, isOwned])
|
|
||||||
.flat();
|
|
||||||
const [rows, _] = await db.execute(
|
|
||||||
`
|
|
||||||
SELECT
|
|
||||||
closet_hangers.item_id AS item_id, closet_hangers.owned AS is_owned,
|
|
||||||
count(DISTINCT closet_hangers.user_id) AS users_count
|
|
||||||
FROM closet_hangers
|
|
||||||
INNER JOIN users ON users.id = closet_hangers.user_id
|
|
||||||
LEFT JOIN closet_lists ON closet_lists.id = closet_hangers.list_id
|
|
||||||
WHERE (
|
|
||||||
(${qs})
|
|
||||||
AND (
|
|
||||||
(closet_hangers.list_id IS NOT NULL AND closet_lists.visibility >= 2)
|
|
||||||
OR (
|
|
||||||
closet_hangers.list_id IS NULL AND closet_hangers.owned = 1
|
|
||||||
AND users.owned_closet_hangers_visibility >= 2
|
|
||||||
)
|
|
||||||
OR (
|
|
||||||
closet_hangers.list_id IS NULL AND closet_hangers.owned = 0
|
|
||||||
AND users.wanted_closet_hangers_visibility >= 2
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
GROUP BY closet_hangers.item_id, closet_hangers.owned;
|
|
||||||
`,
|
|
||||||
values
|
|
||||||
);
|
|
||||||
|
|
||||||
const entities = rows.map(normalizeRow);
|
|
||||||
|
|
||||||
return itemIdOwnedPairs.map(({ itemId, isOwned }) => {
|
|
||||||
// NOTE: There may be no matching row, if there are 0 such trades.
|
|
||||||
const entity = entities.find(
|
|
||||||
(e) => e.itemId === itemId && Boolean(e.isOwned) === isOwned
|
|
||||||
);
|
|
||||||
return entity ? entity.usersCount : 0;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
{ cacheKeyFn: ({ itemId, isOwned }) => `${itemId}-${isOwned}` }
|
|
||||||
);
|
|
||||||
|
|
||||||
const buildItemTradesLoader = (db, loaders) =>
|
const buildItemTradesLoader = (db, loaders) =>
|
||||||
new DataLoader(
|
new DataLoader(
|
||||||
async (itemIdOwnedPairs) => {
|
async (itemIdOwnedPairs) => {
|
||||||
|
@ -1261,7 +1212,6 @@ function buildLoaders(db) {
|
||||||
db
|
db
|
||||||
);
|
);
|
||||||
loaders.itemAllOccupiedZonesLoader = buildItemAllOccupiedZonesLoader(db);
|
loaders.itemAllOccupiedZonesLoader = buildItemAllOccupiedZonesLoader(db);
|
||||||
loaders.itemTradeCountsLoader = buildItemTradeCountsLoader(db);
|
|
||||||
loaders.itemTradesLoader = buildItemTradesLoader(db, loaders);
|
loaders.itemTradesLoader = buildItemTradesLoader(db, loaders);
|
||||||
loaders.petTypeLoader = buildPetTypeLoader(db, loaders);
|
loaders.petTypeLoader = buildPetTypeLoader(db, loaders);
|
||||||
loaders.petTypeBySpeciesAndColorLoader = buildPetTypeBySpeciesAndColorLoader(
|
loaders.petTypeBySpeciesAndColorLoader = buildPetTypeBySpeciesAndColorLoader(
|
||||||
|
|
|
@ -29,6 +29,7 @@ const typeDefs = gql`
|
||||||
currentUserWantsThis: Boolean! @cacheControl(scope: PRIVATE)
|
currentUserWantsThis: Boolean! @cacheControl(scope: PRIVATE)
|
||||||
|
|
||||||
# How many users are offering/seeking this in their public trade lists.
|
# How many users are offering/seeking this in their public trade lists.
|
||||||
|
# Excludes users that seem relatively inactive.
|
||||||
numUsersOfferingThis: Int! @cacheControl(maxAge: ${oneHour})
|
numUsersOfferingThis: Int! @cacheControl(maxAge: ${oneHour})
|
||||||
numUsersSeekingThis: Int! @cacheControl(maxAge: ${oneHour})
|
numUsersSeekingThis: Int! @cacheControl(maxAge: ${oneHour})
|
||||||
|
|
||||||
|
@ -268,19 +269,55 @@ const resolvers = {
|
||||||
return closetHangers.some((h) => h.itemId === id && !h.owned);
|
return closetHangers.some((h) => h.itemId === id && !h.owned);
|
||||||
},
|
},
|
||||||
|
|
||||||
numUsersOfferingThis: async ({ id }, _, { itemTradeCountsLoader }) => {
|
numUsersOfferingThis: async (
|
||||||
const count = await itemTradeCountsLoader.load({
|
{ id },
|
||||||
|
_,
|
||||||
|
{ itemTradesLoader, userLastTradeActivityLoader }
|
||||||
|
) => {
|
||||||
|
// First, get the trades themselves. TODO: Optimize into one query?
|
||||||
|
const trades = await itemTradesLoader.load({
|
||||||
itemId: id,
|
itemId: id,
|
||||||
isOwned: true,
|
isOwned: true,
|
||||||
});
|
});
|
||||||
return count;
|
|
||||||
|
// Then, get the last active dates for those users.
|
||||||
|
const userIds = trades.map((t) => t.user.id);
|
||||||
|
const lastActiveDates = await userLastTradeActivityLoader.loadMany(
|
||||||
|
userIds
|
||||||
|
);
|
||||||
|
|
||||||
|
// Finally, count how many of those dates were in the last 6 months.
|
||||||
|
// Those trades get to be in the count!
|
||||||
|
const sixMonthsAgo = new Date();
|
||||||
|
sixMonthsAgo.setMonth(sixMonthsAgo.getMonth() - 6);
|
||||||
|
const numTrades = lastActiveDates.filter((d) => d > sixMonthsAgo).length;
|
||||||
|
|
||||||
|
return numTrades;
|
||||||
},
|
},
|
||||||
numUsersSeekingThis: async ({ id }, _, { itemTradeCountsLoader }) => {
|
numUsersSeekingThis: async (
|
||||||
const count = await itemTradeCountsLoader.load({
|
{ id },
|
||||||
|
_,
|
||||||
|
{ itemTradesLoader, userLastTradeActivityLoader }
|
||||||
|
) => {
|
||||||
|
// First, get the trades themselves. TODO: Optimize into one query?
|
||||||
|
const trades = await itemTradesLoader.load({
|
||||||
itemId: id,
|
itemId: id,
|
||||||
isOwned: false,
|
isOwned: false,
|
||||||
});
|
});
|
||||||
return count;
|
|
||||||
|
// Then, get the last active dates for those users.
|
||||||
|
const userIds = trades.map((t) => t.user.id);
|
||||||
|
const lastActiveDates = await userLastTradeActivityLoader.loadMany(
|
||||||
|
userIds
|
||||||
|
);
|
||||||
|
|
||||||
|
// Finally, count how many of those dates were in the last 6 months.
|
||||||
|
// Those trades get to be in the count!
|
||||||
|
const sixMonthsAgo = new Date();
|
||||||
|
sixMonthsAgo.setMonth(sixMonthsAgo.getMonth() - 6);
|
||||||
|
const numTrades = lastActiveDates.filter((d) => d > sixMonthsAgo).length;
|
||||||
|
|
||||||
|
return numTrades;
|
||||||
},
|
},
|
||||||
|
|
||||||
tradesOffering: async ({ id }, _, { itemTradesLoader }) => {
|
tradesOffering: async ({ id }, _, { itemTradesLoader }) => {
|
||||||
|
|
Loading…
Reference in a new issue