diff --git a/backend/src/schema/resolvers/searches.js b/backend/src/schema/resolvers/searches.js
index 250746835..c6896c10f 100644
--- a/backend/src/schema/resolvers/searches.js
+++ b/backend/src/schema/resolvers/searches.js
@@ -19,7 +19,8 @@ const cypherTemplate = (setup) => `
const simpleWhereClause =
'WHERE score >= 0.0 AND NOT (resource.deleted = true OR resource.disabled = true)'
-const postWhereClause = `WHERE score >= 0.0 AND NOT (
+const postWhereClause = `WHERE score >= 0.0
+ AND NOT (
author.deleted = true OR author.disabled = true
OR resource.deleted = true OR resource.disabled = true
OR (:User {id: $userId})-[:MUTED]->(author)
@@ -66,26 +67,22 @@ const searchHashtagsSetup = {
resultKeyName: 'hashtags',
}
+const countSetup = {
+ returnClause: 'toString(size(collect(resource)))',
+ limit: '',
+}
+
const countUsersSetup = {
...searchUsersSetup,
- ...{
- returnClause: 'toString(size(collect(resource)))',
- limit: '',
- },
+ ...countSetup,
}
const countPostsSetup = {
...searchPostsSetup,
- ...{
- returnClause: 'toString(size(collect(resource)))',
- limit: '',
- },
+ ...countSetup,
}
const countHashtagsSetup = {
...searchHashtagsSetup,
- ...{
- returnClause: 'toString(size(collect(resource)))',
- limit: '',
- },
+ ...countSetup,
}
const searchResultPromise = async (session, setup, params) => {
@@ -94,23 +91,20 @@ const searchResultPromise = async (session, setup, params) => {
})
}
-const getSearchResults = async (context, setup, params) => {
- const session = context.driver.session()
- try {
- const results = await searchResultPromise(session, setup, params)
- log(results)
- return results.records.map((r) => r.get('result'))
- } finally {
- session.close()
- }
+const searchResultCallback = (result) => {
+ return result.records.map((r) => r.get('result'))
}
-const countSearchResults = async (context, setup, params) => {
+const countResultCallback = (result) => {
+ return result.records[0].get('result')
+}
+
+const getSearchResults = async (context, setup, params, resultCallback = searchResultCallback) => {
const session = context.driver.session()
try {
const results = await searchResultPromise(session, setup, params)
log(results)
- return results.records[0].get('result')
+ return resultCallback(results)
} finally {
session.close()
}
@@ -127,15 +121,19 @@ export default {
Query: {
searchPosts: async (_parent, args, context, _resolveInfo) => {
const { query, postsOffset, firstPosts } = args
- // const { id: userId } = context.user
- const userId = '73'
+ const { id: userId } = context.user
return {
- postCount: countSearchResults(context, countPostsSetup, {
- query: queryString(query),
- skip: 0,
- userId,
- }),
+ postCount: getSearchResults(
+ context,
+ countPostsSetup,
+ {
+ query: queryString(query),
+ skip: 0,
+ userId,
+ },
+ countResultCallback,
+ ),
posts: getSearchResults(context, searchPostsSetup, {
query: queryString(query),
skip: postsOffset,
@@ -147,10 +145,15 @@ export default {
searchUsers: async (_parent, args, context, _resolveInfo) => {
const { query, usersOffset, firstUsers } = args
return {
- userCount: countSearchResults(context, countUsersSetup, {
- query: queryString(query),
- skip: 0,
- }),
+ userCount: getSearchResults(
+ context,
+ countUsersSetup,
+ {
+ query: queryString(query),
+ skip: 0,
+ },
+ countResultCallback,
+ ),
users: getSearchResults(context, searchUsersSetup, {
query: queryString(query),
skip: usersOffset,
@@ -161,10 +164,15 @@ export default {
searchHashtags: async (_parent, args, context, _resolveInfo) => {
const { query, hashtagsOffset, firstHashtags } = args
return {
- hashtagCount: countSearchResults(context, countHashtagsSetup, {
- query: queryString(query),
- skip: 0,
- }),
+ hashtagCount: getSearchResults(
+ context,
+ countHashtagsSetup,
+ {
+ query: queryString(query),
+ skip: 0,
+ },
+ countResultCallback,
+ ),
hashtags: getSearchResults(context, searchHashtagsSetup, {
query: queryString(query),
skip: hashtagsOffset,
@@ -187,83 +195,24 @@ export default {
userId,
} */
- const postCypher = `
- CALL db.index.fulltext.queryNodes('post_fulltext_search', $query)
- YIELD node as resource, score
- MATCH (resource)<-[:WROTE]-(author:User)
- WHERE score >= 0.0
- AND NOT (
- author.deleted = true OR author.disabled = true
- OR resource.deleted = true OR resource.disabled = true
- OR (:User {id: $userId})-[:MUTED]->(author)
- )
- WITH resource, author,
- [(resource)<-[:COMMENTS]-(comment:Comment) | comment] as comments,
- [(resource)<-[:SHOUTED]-(user:User) | user] as shouter
- RETURN resource {
- .*,
- __typename: labels(resource)[0],
- author: properties(author),
- commentsCount: toString(size(comments)),
- shoutedCount: toString(size(shouter))
- }
- LIMIT $limit
- `
-
- const userCypher = `
- CALL db.index.fulltext.queryNodes('user_fulltext_search', $query)
- YIELD node as resource, score
- MATCH (resource)
- WHERE score >= 0.0
- AND NOT (resource.deleted = true OR resource.disabled = true)
- RETURN resource {.*, __typename: labels(resource)[0]}
- LIMIT $limit
- `
- const tagCypher = `
- CALL db.index.fulltext.queryNodes('tag_fulltext_search', $query)
- YIELD node as resource, score
- MATCH (resource)
- WHERE score >= 0.0
- AND NOT (resource.deleted = true OR resource.disabled = true)
- RETURN resource {.*, __typename: labels(resource)[0]}
- LIMIT $limit
- `
-
- const myQuery = queryString(query)
-
- const session = context.driver.session()
- const searchResultPromise = session.readTransaction(async (transaction) => {
- const postTransactionResponse = transaction.run(postCypher, {
- query: myQuery,
+ return [
+ ...(await getSearchResults(context, searchPostsSetup, {
+ query: queryString(query),
+ skip: 0,
limit,
userId,
- })
- const userTransactionResponse = transaction.run(userCypher, {
- query: myQuery,
+ })),
+ ...(await getSearchResults(context, searchUsersSetup, {
+ query: queryString(query),
+ skip: 0,
limit,
- })
- const tagTransactionResponse = transaction.run(tagCypher, {
- query: myQuery,
+ })),
+ ...(await getSearchResults(context, searchHashtagsSetup, {
+ query: queryString(query),
+ skip: 0,
limit,
- })
- return Promise.all([
- postTransactionResponse,
- userTransactionResponse,
- tagTransactionResponse,
- ])
- })
-
- try {
- const [postResults, userResults, tagResults] = await searchResultPromise
- log(postResults)
- log(userResults)
- log(tagResults)
- return [...postResults.records, ...userResults.records, ...tagResults.records].map((r) =>
- r.get('resource'),
- )
- } finally {
- session.close()
- }
+ })),
+ ]
},
},
}
diff --git a/backend/src/schema/resolvers/searches.spec.js b/backend/src/schema/resolvers/searches.spec.js
index 3d7bd039d..5c08497cc 100644
--- a/backend/src/schema/resolvers/searches.spec.js
+++ b/backend/src/schema/resolvers/searches.spec.js
@@ -24,12 +24,12 @@ beforeAll(async () => {
})
afterAll(async () => {
- await cleanDatabase()
+ // await cleanDatabase()
})
const searchQuery = gql`
query($query: String!) {
- findResources(query: $query, limit: 5) {
+ searchResults(query: $query, limit: 5) {
__typename
... on Post {
id
@@ -65,7 +65,7 @@ describe('resolvers/searches', () => {
variables = { query: 'John' }
await expect(query({ query: searchQuery, variables })).resolves.toMatchObject({
data: {
- findResources: [
+ searchResults: [
{
id: 'a-user',
name: 'John Doe',
@@ -95,7 +95,7 @@ describe('resolvers/searches', () => {
variables = { query: 'beitrag' }
await expect(query({ query: searchQuery, variables })).resolves.toMatchObject({
data: {
- findResources: [
+ searchResults: [
{
__typename: 'Post',
id: 'a-post',
@@ -114,7 +114,7 @@ describe('resolvers/searches', () => {
variables = { query: 'BEITRAG' }
await expect(query({ query: searchQuery, variables })).resolves.toMatchObject({
data: {
- findResources: [
+ searchResults: [
{
__typename: 'Post',
id: 'a-post',
@@ -132,7 +132,7 @@ describe('resolvers/searches', () => {
it('returns empty search results', async () => {
await expect(
query({ query: searchQuery, variables: { query: 'Unfug' } }),
- ).resolves.toMatchObject({ data: { findResources: [] } })
+ ).resolves.toMatchObject({ data: { searchResults: [] } })
})
})
@@ -189,7 +189,7 @@ und hinter tausend Stäben keine Welt.`,
variables = { query: 'beitrag' }
await expect(query({ query: searchQuery, variables })).resolves.toMatchObject({
data: {
- findResources: expect.arrayContaining([
+ searchResults: expect.arrayContaining([
{
__typename: 'Post',
id: 'a-post',
@@ -216,7 +216,7 @@ und hinter tausend Stäben keine Welt.`,
variables = { query: 'tee-ei' }
await expect(query({ query: searchQuery, variables })).resolves.toMatchObject({
data: {
- findResources: [
+ searchResults: [
{
__typename: 'Post',
id: 'g-post',
@@ -235,7 +235,7 @@ und hinter tausend Stäben keine Welt.`,
variables = { query: '„teeei“' }
await expect(query({ query: searchQuery, variables })).resolves.toMatchObject({
data: {
- findResources: [
+ searchResults: [
{
__typename: 'Post',
id: 'g-post',
@@ -256,7 +256,7 @@ und hinter tausend Stäben keine Welt.`,
variables = { query: '(a - b)²' }
await expect(query({ query: searchQuery, variables })).resolves.toMatchObject({
data: {
- findResources: [
+ searchResults: [
{
__typename: 'Post',
id: 'c-post',
@@ -277,7 +277,7 @@ und hinter tausend Stäben keine Welt.`,
variables = { query: '(a-b)²' }
await expect(query({ query: searchQuery, variables })).resolves.toMatchObject({
data: {
- findResources: [
+ searchResults: [
{
__typename: 'Post',
id: 'c-post',
@@ -298,7 +298,7 @@ und hinter tausend Stäben keine Welt.`,
variables = { query: '+ b² 2.' }
await expect(query({ query: searchQuery, variables })).resolves.toMatchObject({
data: {
- findResources: [
+ searchResults: [
{
__typename: 'Post',
id: 'c-post',
@@ -321,7 +321,7 @@ und hinter tausend Stäben keine Welt.`,
variables = { query: 'der panther' }
await expect(query({ query: searchQuery, variables })).resolves.toMatchObject({
data: {
- findResources: [
+ searchResults: [
{
__typename: 'Post',
id: 'd-post',
@@ -349,7 +349,7 @@ und hinter tausend Stäben keine Welt.`,
variables = { query: 'Vorü Subs' }
await expect(query({ query: searchQuery, variables })).resolves.toMatchObject({
data: {
- findResources: expect.arrayContaining([
+ searchResults: expect.arrayContaining([
{
__typename: 'Post',
id: 'd-post',
@@ -395,7 +395,7 @@ und hinter tausend Stäben keine Welt.`,
variables = { query: '-maria-' }
await expect(query({ query: searchQuery, variables })).resolves.toMatchObject({
data: {
- findResources: expect.arrayContaining([
+ searchResults: expect.arrayContaining([
{
__typename: 'User',
id: 'c-user',
@@ -440,7 +440,7 @@ und hinter tausend Stäben keine Welt.`,
variables = { query: 'beitrag' }
await expect(query({ query: searchQuery, variables })).resolves.toMatchObject({
data: {
- findResources: expect.not.arrayContaining([
+ searchResults: expect.not.arrayContaining([
{
__typename: 'Post',
id: 'muted-post',
@@ -465,7 +465,7 @@ und hinter tausend Stäben keine Welt.`,
variables = { query: 'myha' }
await expect(query({ query: searchQuery, variables })).resolves.toMatchObject({
data: {
- findResources: [
+ searchResults: [
{
__typename: 'Tag',
id: 'myHashtag',
diff --git a/webapp/components/_new/features/SearchResults/SearchResults.story.js b/webapp/components/_new/features/SearchResults/SearchResults.story.js
index 1c8c9cb08..223152de2 100644
--- a/webapp/components/_new/features/SearchResults/SearchResults.story.js
+++ b/webapp/components/_new/features/SearchResults/SearchResults.story.js
@@ -11,7 +11,7 @@ import { user } from '~/components/UserTeaser/UserTeaser.story.js'
helpers.init()
-const postMock = fields => {
+const postMock = (fields) => {
return {
...post,
id: faker.random.uuid(),
@@ -24,7 +24,7 @@ const postMock = fields => {
}
}
-const userMock = fields => {
+const userMock = (fields) => {
return {
...user,
id: faker.random.uuid(),
diff --git a/webapp/components/_new/features/SearchResults/SearchResults.vue b/webapp/components/_new/features/SearchResults/SearchResults.vue
index 46d78dd43..78c9ed11c 100644
--- a/webapp/components/_new/features/SearchResults/SearchResults.vue
+++ b/webapp/components/_new/features/SearchResults/SearchResults.vue
@@ -15,7 +15,7 @@
- {{postPage}}
+ {{ postPage }}
0
},
+ hasMorePosts() {
+ return (this.postPage + 1) * this.pageSize <= this.postCount
+ },
+ hasMoreUsers() {
+ return (this.userPage + 1) * this.pageSize <= this.userCount
+ },
+ hasMoreHashtags() {
+ return (this.hashtagPage + 1) * this.pageSize <= this.hashtagCount
+ },
},
methods: {
switchTab(tab) {
this.activeTab = tab
},
previousPosts() {
- this.postsOffset = this.postPage * this.pageSize
this.postPage--
+ this.postsOffset = this.postPage * this.pageSize
},
nextPosts() {
this.postsOffset += this.pageSize
this.postPage++
},
previousUsers() {
- this.usersOffset = Math.max(this.usersOffset - this.pageSize, 0)
this.userPage--
+ this.usersOffset = this.userPage * this.pageSize
},
nextUsers() {
this.usersOffset += this.pageSize
this.userPage++
},
previousHashtags() {
- this.usersOffset = Math.max(this.usersOffset - this.pageSize, 0)
this.hashtagPage--
+ this.hashtagsOffset = this.hashtagPage * this.pageSize
},
nextHashtags() {
- this.usersOffset += this.pageSize
+ this.hashtagsOffset += this.pageSize
this.hashtagPage++
},
},
@@ -197,7 +201,6 @@ export default {
update({ searchPosts }) {
this.posts = searchPosts.posts
this.postCount = searchPosts.postCount
- this.hasMorePosts = this.postCount >= (this.pageSize * this.postPage)
if (searchPosts.posts.length) this.activeTab = 'Post'
},
fetchPolicy: 'cache-and-network',
@@ -220,33 +223,36 @@ export default {
update({ searchUsers }) {
this.users = searchUsers.users
this.userCount = searchUsers.userCount
- this.hasMoreUsers = this.users.length >= this.pageSize
if (!searchPosts.posts.length && searchUsers.users.length) this.activeTab = 'User'
},
fetchPolicy: 'cache-and-network',
},
searchHashtags: {
- query() {
- return searchHashtags
- },
- variables() {
- const { firstHashtags, hashtagsOffset, search } = this
- return {
- query: search,
- firstHashtags,
- hashtagsOffset,
- }
- },
- skip() {
- return !this.search
- },
- update({ searchHashtags }) {
- this.hashtags = searchHashtags.hashtags
- this.hashtagCount = searchHashtags.hashtagCount
- this.hasMoreHashtags = this.hashtags.length >= this.pageSize
- if (!searchPosts.posts.length && !searchUsers.users.length && searchHashtags.hashtags.length) this.activeTab = 'Hashtag'
- },
- fetchPolicy: 'cache-and-network',
+ query() {
+ return searchHashtags
+ },
+ variables() {
+ const { firstHashtags, hashtagsOffset, search } = this
+ return {
+ query: search,
+ firstHashtags,
+ hashtagsOffset,
+ }
+ },
+ skip() {
+ return !this.search
+ },
+ update({ searchHashtags }) {
+ this.hashtags = searchHashtags.hashtags
+ this.hashtagCount = searchHashtags.hashtagCount
+ if (
+ !searchPosts.posts.length &&
+ !searchUsers.users.length &&
+ searchHashtags.hashtags.length
+ )
+ this.activeTab = 'Hashtag'
+ },
+ fetchPolicy: 'cache-and-network',
},
},
}
diff --git a/webapp/graphql/Search.js b/webapp/graphql/Search.js
index 98bd007f4..b298b48c1 100644
--- a/webapp/graphql/Search.js
+++ b/webapp/graphql/Search.js
@@ -7,8 +7,7 @@ export const searchQuery = gql`
${tagsCategoriesAndPinnedFragment}
query($query: String!) {
- searchResults(query: $query, limit: 5)
- {
+ searchResults(query: $query, limit: 5) {
__typename
... on Post {
...post
@@ -38,16 +37,16 @@ export const searchPosts = gql`
searchPosts(query: $query, firstPosts: $firstPosts, postsOffset: $postsOffset) {
postCount
posts {
- __typename
- ...post
- ...tagsCategoriesAndPinned
- commentsCount
- shoutedCount
- author {
- ...user
+ __typename
+ ...post
+ ...tagsCategoriesAndPinned
+ commentsCount
+ shoutedCount
+ author {
+ ...user
+ }
}
}
- }
}
`
@@ -58,21 +57,20 @@ export const searchUsers = gql`
searchUsers(query: $query, firstUsers: $firstUsers, usersOffset: $usersOffset) {
userCount
users {
- __typename
- ...user
+ __typename
+ ...user
}
}
}
`
export const searchHashtags = gql`
-
query($query: String!, $firstHashtags: Int, $hashtagsOffset: Int) {
searchHashtags(query: $query, firstHashtags: $firstHashtags, hashtagsOffset: $hashtagsOffset) {
hashtagCount
hashtags {
- __typename
- id
+ __typename
+ id
}
}
}