diff --git a/backend/src/schema/resolvers/searches.js b/backend/src/schema/resolvers/searches.js index c49b3a239..ca64ec14b 100644 --- a/backend/src/schema/resolvers/searches.js +++ b/backend/src/schema/resolvers/searches.js @@ -6,7 +6,13 @@ export default { const { query, limit } = args const { id: thisUserId } = context.user // see http://lucene.apache.org/core/8_3_1/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#package.description - const myQuery = query + '*' + const myQuery = query + .replace(/\s+/g, ' ') + .replace(/[[@#:*~\\$|^\]?/"'(){}+?!,.-]/g, '') + .split(' ') + .map(s => '"' + s + '"*') + .join(' ') + // console.log(myQuery) const postCypher = ` CALL db.index.fulltext.queryNodes('post_fulltext_search', $query) YIELD node as resource, score @@ -40,6 +46,15 @@ export default { RETURN resource {.*, __typename: labels(resource)[0]} LIMIT $limit ` + /* + const tagCypher = ` +MATCH (resource:Tag) +WHERE resource.id CONTAINS $query +AND NOT(resource.deleted = true OR resource.disabled = true) +RETURN resource {.*, __typename: labels(resource)[0]} +LIMIT $limit +` +*/ const session = context.driver.session() const searchResultPromise = session.readTransaction(async transaction => { @@ -53,14 +68,20 @@ export default { limit, thisUserId, }) - return Promise.all([postTransactionResponse, userTransactionResponse]) + /* + const tagTransactionResponse = transaction.run(tagCypher, { + query: query, + limit, + }) */ + return Promise.all([postTransactionResponse, userTransactionResponse]) //, tagTransactionResponse }) try { - const [postResults, userResults] = await searchResultPromise + const [postResults, userResults] = await searchResultPromise //, tagResults log(postResults) log(userResults) - return [...postResults.records, ...userResults.records].map(r => r.get('resource')) + // log(tagResults) + return [...postResults.records, ...userResults.records].map(r => r.get('resource')) //, ...tagResults.records } finally { session.close() } @@ -68,7 +89,27 @@ export default { }, } -/* +/* order users by closest geolocation could look like this + +MATCH (u1:User { id: $thisUserId })-[:IS_IN]->(l1:Location) +MATCH (u2:User)-[:IS_IN]->(l2:Location) +WHERE NOT(u2.id = $thisUserId) +AND NOT (u2.deleted = true OR u2.disabled = true +OR (u1)-[:BLOCKED]-(u2)) +WITH point({longitude: l1.lng, latitude: l1.lat}) AS P1, +point({longitude: l2.lng, latitude: l2.lat}) AS P2, +u2 AS otherUsers +WITH distance(P1, P2) AS Distance, +otherUsers AS users +ORDER BY Distance +RETURN users + +*/ + +/* This query is to test if the calculation of distances works. +See: +https://github.com/Human-Connection/Human-Connection/issues/2587 + MATCH (u1:User { name: 'Huey' })-[:IS_IN]->(l1:Location) MATCH (u2:User)-[:IS_IN]->(l2:Location) WHERE NOT(u2.name = 'Huey') diff --git a/backend/src/schema/types/type/Search.gql b/backend/src/schema/types/type/Search.gql index 2c22fa61f..1ce38001d 100644 --- a/backend/src/schema/types/type/Search.gql +++ b/backend/src/schema/types/type/Search.gql @@ -1,4 +1,4 @@ -union SearchResult = Post | User +union SearchResult = Post | User | Tag type Query { findResources(query: String!, limit: Int = 5): [SearchResult]! diff --git a/webapp/components/generic/SearchHeading/SearchHeading.vue b/webapp/components/generic/SearchHeading/SearchHeading.vue index 9a4602980..2819eda0b 100644 --- a/webapp/components/generic/SearchHeading/SearchHeading.vue +++ b/webapp/components/generic/SearchHeading/SearchHeading.vue @@ -1,5 +1,5 @@ @@ -59,12 +65,14 @@ import { isEmpty } from 'lodash' import SearchHeading from '~/components/generic/SearchHeading/SearchHeading.vue' import SearchPost from '~/components/generic/SearchPost/SearchPost.vue' +import SearchTag from '~/components/generic/SearchTag/SearchTag.vue' import HcUser from '~/components/User/User.vue' export default { components: { SearchHeading, SearchPost, + SearchTag, HcUser, }, props: { @@ -104,10 +112,10 @@ export default { }, handleInput(event) { clearTimeout(this.searchProcess) - this.value = event.target ? event.target.value.trim() : '' + this.value = event.target ? event.target.value.replace(/\s+/g, ' ').trim() : '' this.isOpen = true this.unprocessedSearchInput = this.value - if (isEmpty(this.value) || this.value.length < 3) { + if (isEmpty(this.value) || this.value.replace(/\s+/g, '').length < 3) { return } this.searchProcess = setTimeout(() => { diff --git a/webapp/graphql/Search.js b/webapp/graphql/Search.js index 9b142b429..ab34b58b6 100644 --- a/webapp/graphql/Search.js +++ b/webapp/graphql/Search.js @@ -19,6 +19,9 @@ export const findResourcesQuery = gql` ... on User { ...user } + ... on Tag { + id + } } } ` diff --git a/webapp/locales/de.json b/webapp/locales/de.json index f3a3b3ce6..7b3cfb8b1 100644 --- a/webapp/locales/de.json +++ b/webapp/locales/de.json @@ -518,7 +518,8 @@ "failed": "Nichts gefunden", "heading": { "Post": "Beiträge", - "User": "Benutzer" + "User": "Benutzer", + "Tag": "Hashtags" } }, "components": { diff --git a/webapp/locales/en.json b/webapp/locales/en.json index e1a42b913..02f354a74 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -202,7 +202,8 @@ "failed": "Nothing found", "heading": { "Post": "Posts", - "User": "Users" + "User": "Users", + "Tag": "Hashtags" } }, "settings": {