checkpoint: pre-refactor state before fixing P0/P1 issues
This commit is contained in:
@@ -2,49 +2,119 @@ const cloud = require('wx-server-sdk')
|
||||
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
|
||||
const db = cloud.database()
|
||||
const _ = db.command
|
||||
const $ = db.command.aggregate
|
||||
const PAGE_SIZE = 10
|
||||
|
||||
// 按 where 条件取一页,时间倒序(关注流 / 个人主页 / 附近兜底共用)
|
||||
async function listByWhere(where, skip) {
|
||||
const col = db.collection('posts').where(where)
|
||||
const countRes = await col.count()
|
||||
const res = await col
|
||||
.orderBy('createdAt', 'desc')
|
||||
.skip(skip)
|
||||
.limit(PAGE_SIZE)
|
||||
.get()
|
||||
return {
|
||||
posts: res.data,
|
||||
total: countRes.total,
|
||||
hasMore: skip + res.data.length < countRes.total,
|
||||
}
|
||||
}
|
||||
|
||||
// 热门:热度分 = (点赞×3 + 评论×5 + 1) / (帖龄小时数 + 2)^1.5
|
||||
// 类 Hacker News 的重力衰减,互动加分、随时间下沉;同分按发布时间倒序
|
||||
async function listHot(skip) {
|
||||
const countRes = await db.collection('posts').count()
|
||||
const res = await db.collection('posts').aggregate()
|
||||
.addFields({
|
||||
hotScore: $.divide([
|
||||
$.add([
|
||||
$.multiply([$.ifNull(['$likeCount', 0]), 3]),
|
||||
$.multiply([$.ifNull(['$commentCount', 0]), 5]),
|
||||
1,
|
||||
]),
|
||||
$.pow([
|
||||
$.add([
|
||||
$.divide([$.subtract([new Date(), '$createdAt']), 3600000]),
|
||||
2,
|
||||
]),
|
||||
1.5,
|
||||
]),
|
||||
]),
|
||||
})
|
||||
.sort({ hotScore: -1, createdAt: -1 })
|
||||
.skip(skip)
|
||||
.limit(PAGE_SIZE)
|
||||
.end()
|
||||
return {
|
||||
posts: res.list,
|
||||
total: countRes.total,
|
||||
hasMore: skip + res.list.length < countRes.total,
|
||||
}
|
||||
}
|
||||
|
||||
// 附近:geo.near 按距离由近到远,依赖 posts.geo 的地理位置索引;
|
||||
// 索引未建或查询失败时回退为矩形围栏 + 时间倒序。
|
||||
// $near 不支持 count,用多取一条判断 hasMore,total 为近似值
|
||||
async function listNearby(latitude, longitude, skip) {
|
||||
try {
|
||||
const res = await db.collection('posts')
|
||||
.where({
|
||||
geo: _.geoNear({
|
||||
geometry: db.Geo.Point(longitude, latitude),
|
||||
maxDistance: 10000,
|
||||
}),
|
||||
})
|
||||
.skip(skip)
|
||||
.limit(PAGE_SIZE + 1)
|
||||
.get()
|
||||
const hasMore = res.data.length > PAGE_SIZE
|
||||
const posts = hasMore ? res.data.slice(0, PAGE_SIZE) : res.data
|
||||
return { posts, total: skip + posts.length + (hasMore ? 1 : 0), hasMore }
|
||||
} catch (e) {
|
||||
return listByWhere(
|
||||
_.and([
|
||||
{ 'location.latitude': _.gt(latitude - 0.1) },
|
||||
{ 'location.latitude': _.lt(latitude + 0.1) },
|
||||
{ 'location.longitude': _.gt(longitude - 0.15) },
|
||||
{ 'location.longitude': _.lt(longitude + 0.15) },
|
||||
]),
|
||||
skip
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
exports.main = async (event, context) => {
|
||||
const { OPENID } = cloud.getWXContext()
|
||||
const { page = 0, type = 'hot', userId, latitude, longitude } = event
|
||||
const skip = page * PAGE_SIZE
|
||||
|
||||
try {
|
||||
let query = db.collection('posts')
|
||||
const skip = page * PAGE_SIZE
|
||||
let result
|
||||
|
||||
if (userId) {
|
||||
// 某用户的帖子
|
||||
query = query.where({ authorId: userId })
|
||||
result = await listByWhere({ authorId: userId }, skip)
|
||||
} else if (type === 'feed') {
|
||||
// 关注的用户帖子
|
||||
// 关注流:我关注的人 + 自己
|
||||
const followsRes = await db.collection('follows')
|
||||
.where({ followerId: OPENID })
|
||||
.field({ followeeId: true })
|
||||
.get()
|
||||
const followeeIds = followsRes.data.map(f => f.followeeId)
|
||||
followeeIds.push(OPENID)
|
||||
query = query.where({ authorId: _.in(followeeIds) })
|
||||
result = await listByWhere({ authorId: _.in(followeeIds) }, skip)
|
||||
} else if (type === 'nearby' && latitude && longitude) {
|
||||
// 附近帖子:使用地理围栏查询(简化版,用 geo_near)
|
||||
query = query.where(
|
||||
_.and([
|
||||
{ 'location.latitude': _.gt(latitude - 0.1) },
|
||||
{ 'location.latitude': _.lt(latitude + 0.1) },
|
||||
{ 'location.longitude': _.gt(longitude - 0.15) },
|
||||
{ 'location.longitude': _.lt(longitude + 0.15) },
|
||||
])
|
||||
)
|
||||
result = await listNearby(latitude, longitude, skip)
|
||||
} else {
|
||||
result = await listHot(skip)
|
||||
}
|
||||
// type === 'hot' 全量按热度排序
|
||||
|
||||
const total = await query.count()
|
||||
const postsRes = await query
|
||||
.orderBy('createdAt', 'desc')
|
||||
.skip(skip)
|
||||
.limit(PAGE_SIZE)
|
||||
.get()
|
||||
const { posts, total, hasMore } = result
|
||||
|
||||
const posts = postsRes.data
|
||||
if (posts.length === 0) {
|
||||
return { code: 0, data: { list: [], total, hasMore: false } }
|
||||
}
|
||||
|
||||
// 批量获取作者信息
|
||||
const authorIds = [...new Set(posts.map(p => p.authorId))]
|
||||
@@ -71,11 +141,7 @@ exports.main = async (event, context) => {
|
||||
|
||||
return {
|
||||
code: 0,
|
||||
data: {
|
||||
list: enriched,
|
||||
total: total.total,
|
||||
hasMore: skip + posts.length < total.total,
|
||||
},
|
||||
data: { list: enriched, total, hasMore },
|
||||
}
|
||||
} catch (e) {
|
||||
return { code: -1, message: e.message }
|
||||
|
||||
Reference in New Issue
Block a user