feat: add MongoDB search method, endpoints, and settings module
deploy-chabokan / deploy (push) Canceled after 0s
deploy-chabokan / deploy (push) Canceled after 0s
This commit is contained in:
@@ -165,15 +165,116 @@ const ensureCollectionExists = async (forceRecreate = false) => {
|
||||
}
|
||||
}
|
||||
|
||||
const settingService = require('../setting/settingService')
|
||||
|
||||
const searchTransactionsMongo = async (inputQuery = {}) => {
|
||||
const page = parseInt(inputQuery.page) || 1
|
||||
const per_page = parseInt(inputQuery.per_page) || parseInt(inputQuery.limit) || 20
|
||||
const mongoQuery = {}
|
||||
|
||||
const q = (inputQuery.query || inputQuery.search || inputQuery.q || '').trim()
|
||||
if (q && q !== '*') {
|
||||
const searchRegex = { $regex: q, $options: 'i' }
|
||||
const orConditions = [
|
||||
{ description: searchRegex },
|
||||
{ userName: searchRegex },
|
||||
{ type: searchRegex },
|
||||
{ status: searchRegex },
|
||||
{ source: searchRegex },
|
||||
]
|
||||
|
||||
if (mongoose.Types.ObjectId.isValid(q)) {
|
||||
orConditions.push({ _id: q })
|
||||
orConditions.push({ propertyId: q })
|
||||
orConditions.push({ userId: q })
|
||||
}
|
||||
|
||||
mongoQuery.$or = orConditions
|
||||
}
|
||||
|
||||
if (inputQuery.type) mongoQuery.type = inputQuery.type
|
||||
if (inputQuery.status) mongoQuery.status = inputQuery.status
|
||||
if (inputQuery.source) mongoQuery.source = inputQuery.source
|
||||
if (inputQuery.propertyId && mongoose.Types.ObjectId.isValid(inputQuery.propertyId)) {
|
||||
mongoQuery.propertyId = inputQuery.propertyId
|
||||
}
|
||||
if (inputQuery.userId && mongoose.Types.ObjectId.isValid(inputQuery.userId)) {
|
||||
mongoQuery.userId = inputQuery.userId
|
||||
}
|
||||
|
||||
let sortObj = { createdAt: -1 }
|
||||
if (inputQuery.sort) {
|
||||
if (typeof inputQuery.sort === 'string') {
|
||||
const parts = inputQuery.sort.split(':')
|
||||
const field = parts[0]
|
||||
const order = parts[1] === 'asc' ? 1 : -1
|
||||
sortObj = { [field]: order }
|
||||
} else if (typeof inputQuery.sort === 'object') {
|
||||
sortObj = inputQuery.sort
|
||||
}
|
||||
}
|
||||
|
||||
const totalCount = await Transaction.countDocuments(mongoQuery)
|
||||
const transactions = await Transaction.find(mongoQuery)
|
||||
.populate('propertyId')
|
||||
.populate('userId')
|
||||
.sort(sortObj)
|
||||
.skip((page - 1) * per_page)
|
||||
.limit(per_page)
|
||||
|
||||
const items = transactions.map((t) => {
|
||||
return {
|
||||
_id: t._id.toString(),
|
||||
id: t._id.toString(),
|
||||
type: t.type || '',
|
||||
status: t.status || '',
|
||||
source: t.source || '',
|
||||
value: t.value || 0,
|
||||
description: t.description || '',
|
||||
createdAt: Math.floor(new Date(t.createdAt || t.date || Date.now()).getTime() / 1000),
|
||||
date: t.date,
|
||||
belongingName: t.propertyId?.name || '',
|
||||
belongingId: t.propertyId?._id ? t.propertyId._id.toString() : '',
|
||||
propertyId: t.propertyId,
|
||||
userName: t.userName || t.userId?.name || '',
|
||||
userId: t.userId,
|
||||
}
|
||||
})
|
||||
|
||||
const pagesCount = Math.ceil(totalCount / per_page) || 1
|
||||
|
||||
return {
|
||||
facets: [],
|
||||
transactions: items,
|
||||
totalCount,
|
||||
pagesCount,
|
||||
searchEngine: 'mongo',
|
||||
}
|
||||
}
|
||||
|
||||
const searchTransactions = async (inputQuery) => {
|
||||
await ensureCollectionExists(false)
|
||||
inputQuery = updateInputQuery(inputQuery, {})
|
||||
try {
|
||||
const setting = await settingService.getSearchSettingByPage('transactions')
|
||||
if (setting && setting.searchMethod === 'mongo') {
|
||||
return searchTransactionsMongo(inputQuery)
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('Failed to fetch search setting for transactions, attempting typesense:', e.message)
|
||||
}
|
||||
|
||||
const tsFeatures = new TsApiFeatures(client, 'transactions', inputQuery).filter().facet().sort().limitFields().paginate().search()
|
||||
try {
|
||||
await ensureCollectionExists(false)
|
||||
const updatedQuery = updateInputQuery({ ...inputQuery }, {})
|
||||
|
||||
let { facets, items, totalCount, pagesCount } = await tsFeatures.execute()
|
||||
const tsFeatures = new TsApiFeatures(client, 'transactions', updatedQuery).filter().facet().sort().limitFields().paginate().search()
|
||||
|
||||
return { facets, transactions: items, totalCount, pagesCount }
|
||||
let { facets, items, totalCount, pagesCount } = await tsFeatures.execute()
|
||||
|
||||
return { facets, transactions: items, totalCount, pagesCount, searchEngine: 'typesense' }
|
||||
} catch (err) {
|
||||
console.warn('Typesense search failed for transactions, falling back to MongoDB:', err.message)
|
||||
return searchTransactionsMongo(inputQuery)
|
||||
}
|
||||
}
|
||||
|
||||
const updateInputQuery = (inputQuery, extraQueries) => {
|
||||
@@ -257,4 +358,6 @@ module.exports = {
|
||||
getTransactionByBelongingId,
|
||||
indexAllTransactions,
|
||||
searchTransactions,
|
||||
searchTransactionsMongo,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user