Как я могу использовать "подсчитывать" и "группировать по" в Prisma 2?
У меня есть эта функция, которая работает:
export const tagsByLabel = async (params) => {
const findManyParams = {
where: { userId: userIdFromSession },
orderBy: { title: 'asc' },
}
if (params) {
const { searchTerm } = params
findManyParams.where.title = { contains: searchTerm }
}
console.log('findManyParams', findManyParams)
const tagsByLabelResult = await db.tag.findMany(findManyParams)
console.log('tagsByLabelResult', tagsByLabelResult)
return tagsByLabelResult
}
Если я буду искать "mex", я вижу:
findManyParams {
where: { userId: 1, title: { contains: 'mex' } },
orderBy: { title: 'asc' }
}
tagsByLabelResult [
{
id: 9,
title: 'mex',
description: 'Mexican food',
userId: 1,
createdAt: 2020-05-03T22:16:09.134Z,
modifiedAt: 2020-05-03T22:16:09.134Z
}
]
А для пустого запроса tagsByLabelResult
содержит все записи тегов.
Как я могу настроить свой tagsByLabel
функция для агрегирования (с помощью "группировки по") записей и вывода "счетчика" для каждой записи tagsByLabelResult
в порядке убывания количества?
tagsByLabelResult [
{
id: 9,
title: 'mex',
description: 'Mexican food',
count: 25,
userId: 1,
createdAt: 2020-05-03T22:16:09.134Z,
modifiedAt: 2020-05-03T22:16:09.134Z
}
]
Я вижу пример DOCS изprisma.user.count()
, но это, похоже, возвращает простой счет результата всего запроса, а не счетчик в виде поля с "группой по".
Я использую RedwoodJs, Prisma 2, Apollo, GraphQL.
2 ответа
На данный момент groupBy
поддержка до сих пор в спецификации здесь, так в настоящее время вы бы только иметь возможность использоватьcount
с конкретным запросом.
В качестве обходного пути вам придется использовать prisma.raw
в настоящее время.
В моем tags.sdl.js
Мне нужно было добавить:
type TagCount {
id: Int!
title: String!
count: Int!
principles: [Principle]
description: String
createdAt: DateTime!
modifiedAt: DateTime!
}
И изменить запрос tagsByLabel(searchTerm: String): [Tag!]!
к tagsByLabel(searchTerm: String): [TagCount!]!
В моем TagsAutocomplete.js
компонент, теперь у меня есть:
export const TagsAutocomplete = ({
onChange,
selectedOptions,
closeMenuOnSelect,
}) => {
const state = {
isLoading: false,
}
const client = useApolloClient()
const promiseOptions = useCallback(
async (searchTerm) => {
try {
const { data } = await client.query({
query: QUERY_TAGS_BY_LABEL,
variables: { searchTerm },
})
console.log('promiseOptions data', data)
const tags = data.tags.map((tag) => {
if (!tag.label.includes('(')) {
//ONEDAY why does the count keep getting appended if this condition isn't checked here?
tag.label = tag.label + ' (' + tag.count + ')'
}
return tag
})
console.log('promiseOptions tags', tags)
return tags
} catch (e) {
console.error('Error fetching tags', e)
}
},
[client]
)
...
И в моем tags.js
сервис, теперь у меня есть:
export const tagsByLabel = async (params) => {
let query = `
SELECT t.*, COUNT(pt.B) as count FROM tag t LEFT JOIN _PrincipleToTag pt ON t.id = pt.B WHERE t.userId = ${userIdFromSession} `
if (params) {
const { searchTerm } = params
if (searchTerm) {
query += `AND t.title LIKE '%${searchTerm}%' `
}
}
query += 'GROUP BY t.id ORDER BY count DESC, t.title ASC;'
console.log('query', query)
const tagsByLabelResult = await db.raw(query)
//TODO get secure parameterization working
console.log('tagsByLabelResult', tagsByLabelResult)
return tagsByLabelResult
}
Но, как упоминалось в комментарии, я все еще пытаюсь понять, как заставить работать безопасную параметризацию.