1
0
mirror of https://github.com/oceanprotocol/market.git synced 2024-12-02 05:57:29 +01:00

Search issues fix (#641)

* search by addresses

* search by asset id

* logs deleted

* search query updated

* search query updated

* search terms differentiated

* asset id hack

* id search hack removed

* restore lock file

Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro>

* remove SearchQuery return type

Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro>

* refine query, add relevance sort

Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro>

* remove old comments

Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro>

* remove white spaces from search term endings

* fix filter by type

* wip on filter with empty search text

* sort by relevance fix

* linting errors fix

* lint fixes

* comment sort by relevance

Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro>

* lint

Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro>

* search by owner and tags fix

* lint  err fix

* fix search

Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro>

Co-authored-by: claudia.holhos <claudia.holhos@hpm.ro>
Co-authored-by: mihaisc <mihai.scarlat@smartcontrol.ro>
This commit is contained in:
claudiaHash 2021-06-15 16:46:49 +03:00 committed by GitHub
parent 6ed92c0bfd
commit eb8c6afb62
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 108 additions and 52 deletions

2
package-lock.json generated
View File

@ -43525,6 +43525,7 @@
"node-abort-controller": "^2.0.0", "node-abort-controller": "^2.0.0",
"save-file": "^2.3.1", "save-file": "^2.3.1",
"uuid": "^8.3.2", "uuid": "^8.3.2",
"web3": "^1.3.5",
"web3-eth-contract": "^1.3.6" "web3-eth-contract": "^1.3.6"
} }
}, },
@ -43599,6 +43600,7 @@
"integrity": "sha512-5vwpq6kbvwkQwKqAoOU3L72GZ3Ta8RRrewKj9OJRolx28KLJJ8Dg9Rf7obRwt5jQA9bkYd8gqzMTrI7H3xLfaw==", "integrity": "sha512-5vwpq6kbvwkQwKqAoOU3L72GZ3Ta8RRrewKj9OJRolx28KLJJ8Dg9Rf7obRwt5jQA9bkYd8gqzMTrI7H3xLfaw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@oclif/config": "^1.15.1",
"@oclif/errors": "^1.3.3", "@oclif/errors": "^1.3.3",
"@oclif/parser": "^3.8.3", "@oclif/parser": "^3.8.3",
"@oclif/plugin-help": "^3", "@oclif/plugin-help": "^3",

View File

@ -23,7 +23,11 @@ export default function SearchBar({
e.preventDefault() e.preventDefault()
if (value === '') value = ' ' if (value === '') value = ' '
const urlEncodedValue = encodeURIComponent(value) const urlEncodedValue = encodeURIComponent(value)
const url = await addExistingParamsToUrl(location, 'text') const url = await addExistingParamsToUrl(location, [
'text',
'owner',
'tags'
])
navigate(`${url}&text=${urlEncodedValue}`) navigate(`${url}&text=${urlEncodedValue}`)
} }
@ -31,7 +35,11 @@ export default function SearchBar({
const searchParams = new URLSearchParams(window.location.href) const searchParams = new URLSearchParams(window.location.href)
const text = searchParams.get('text') const text = searchParams.get('text')
if (text !== ('' || undefined || null)) { if (text !== ('' || undefined || null)) {
const url = await addExistingParamsToUrl(location, 'text') const url = await addExistingParamsToUrl(location, [
'text',
'owner',
'tags'
])
navigate(`${url}&text=%20`) navigate(`${url}&text=%20`)
} }
} }

View File

@ -25,7 +25,7 @@ export default function FilterPrice({
const [serviceSelections, setServiceSelections] = useState<string[]>([]) const [serviceSelections, setServiceSelections] = useState<string[]>([])
async function applyServiceFilter(filterBy: string) { async function applyServiceFilter(filterBy: string) {
let urlLocation = await addExistingParamsToUrl(location, 'serviceType') let urlLocation = await addExistingParamsToUrl(location, ['serviceType'])
if (filterBy && location.search.indexOf('&serviceType') === -1) { if (filterBy && location.search.indexOf('&serviceType') === -1) {
urlLocation = `${urlLocation}&serviceType=${filterBy}` urlLocation = `${urlLocation}&serviceType=${filterBy}`
} }
@ -59,7 +59,7 @@ export default function FilterPrice({
} }
async function applyClearFilter() { async function applyClearFilter() {
let urlLocation = await addExistingParamsToUrl(location, 'serviceType') let urlLocation = await addExistingParamsToUrl(location, ['serviceType'])
urlLocation = `${urlLocation}` urlLocation = `${urlLocation}`

View File

@ -10,7 +10,6 @@ import Sort from './sort'
import { getResults } from './utils' import { getResults } from './utils'
import { navigate } from 'gatsby' import { navigate } from 'gatsby'
import { updateQueryStringParameter } from '../../../utils' import { updateQueryStringParameter } from '../../../utils'
import Loader from '../../atoms/Loader'
import { useOcean } from '../../../providers/Ocean' import { useOcean } from '../../../providers/Ocean'
export default function SearchPage({ export default function SearchPage({
@ -33,7 +32,6 @@ export default function SearchPage({
useEffect(() => { useEffect(() => {
if (!config?.metadataCacheUri) return if (!config?.metadataCacheUri) return
async function initSearch() { async function initSearch() {
setLoading(true) setLoading(true)
setTotalResults(undefined) setTotalResults(undefined)
@ -67,7 +65,7 @@ export default function SearchPage({
<Permission eventType="browse"> <Permission eventType="browse">
<> <>
<div className={styles.search}> <div className={styles.search}>
{(text || owner) && ( {(text || owner || tags) && (
<SearchBar initialValue={(text || owner) as string} /> <SearchBar initialValue={(text || owner) as string} />
)} )}
<div className={styles.row}> <div className={styles.row}>

View File

@ -11,7 +11,10 @@ import classNames from 'classnames/bind'
const cx = classNames.bind(styles) const cx = classNames.bind(styles)
const sortItems = [{ display: 'Published', value: SortTermOptions.Created }] const sortItems = [
// { display: 'Relevance', value: SortTermOptions.Relevance },
{ display: 'Published', value: SortTermOptions.Created }
]
export default function Sort({ export default function Sort({
sortType, sortType,
@ -31,10 +34,11 @@ export default function Sort({
async function sortResults(sortBy?: string, direction?: string) { async function sortResults(sortBy?: string, direction?: string) {
let urlLocation: string let urlLocation: string
if (sortBy) { if (sortBy) {
urlLocation = await addExistingParamsToUrl(location, ['sort'])
urlLocation = `${urlLocation}&sort=${sortBy}` urlLocation = `${urlLocation}&sort=${sortBy}`
setSortType(sortBy) setSortType(sortBy)
} else if (direction) { } else if (direction) {
urlLocation = await addExistingParamsToUrl(location, 'sortOrder') urlLocation = await addExistingParamsToUrl(location, ['sortOrder'])
urlLocation = `${urlLocation}&sortOrder=${direction}` urlLocation = `${urlLocation}&sortOrder=${direction}`
setSortDirection(direction) setSortDirection(direction)
} }

View File

@ -1,12 +1,10 @@
import { import { QueryResult } from '@oceanprotocol/lib/dist/node/metadatacache/MetadataCache'
SearchQuery,
QueryResult
} from '@oceanprotocol/lib/dist/node/metadatacache/MetadataCache'
import { MetadataCache, Logger } from '@oceanprotocol/lib' import { MetadataCache, Logger } from '@oceanprotocol/lib'
import queryString from 'query-string' import queryString from 'query-string'
export const SortTermOptions = { export const SortTermOptions = {
Created: 'created' Created: 'created',
Relevance: '_score'
} as const } as const
type SortTermOptions = typeof SortTermOptions[keyof typeof SortTermOptions] type SortTermOptions = typeof SortTermOptions[keyof typeof SortTermOptions]
@ -39,8 +37,11 @@ function addTypeFilterToQuery(sortTerm: string, typeFilter: string): string {
return sortTerm return sortTerm
} }
function getSortType(): string { function getSortType(sortParam: string): string {
const sortTerm = SortTermOptions.Created const sortTerm =
sortParam === SortTermOptions.Created
? SortTermOptions.Created
: SortTermOptions.Relevance
return sortTerm return sortTerm
} }
@ -54,9 +55,11 @@ export function getSearchQuery(
sort?: string, sort?: string,
sortOrder?: string, sortOrder?: string,
serviceType?: string serviceType?: string
): SearchQuery { ): any {
const sortTerm = getSortType() const sortTerm = getSortType(sort)
const sortValue = sortOrder === SortValueOptions.Ascending ? 1 : -1 const sortValue = sortOrder === SortValueOptions.Ascending ? 1 : -1
const emptySearchTerm = text === undefined || text === ''
let searchTerm = owner let searchTerm = owner
? `(publicKey.owner:${owner})` ? `(publicKey.owner:${owner})`
: tags : tags
@ -67,41 +70,84 @@ export function getSearchQuery(
`(service.attributes.additionalInformation.categories:\"${categories}\")` `(service.attributes.additionalInformation.categories:\"${categories}\")`
: text || '' : text || ''
// HACK: resolves the case sensitivity related to dataTokenInfo.symbol searchTerm = searchTerm.trim()
searchTerm = '*' + searchTerm.toUpperCase() + '*' let modifiedSearchTerm = searchTerm.split(' ').join(' OR ').trim()
modifiedSearchTerm = addTypeFilterToQuery(modifiedSearchTerm, serviceType)
searchTerm = addTypeFilterToQuery(searchTerm, serviceType) searchTerm = addTypeFilterToQuery(searchTerm, serviceType)
const prefixedSearchTerm =
emptySearchTerm && searchTerm
? searchTerm
: !emptySearchTerm && searchTerm
? '*' + searchTerm + '*'
: '**'
return { return {
page: Number(page) || 1, page: Number(page) || 1,
offset: Number(offset) || 21, offset: Number(offset) || 21,
query: { query: {
query_string: { bool: {
query: `${searchTerm} -isInPurgatory:true`, must: [
fields: [ {
'dataTokenInfo.name', bool: {
'dataTokenInfo.symbol', should: [
'service.attributes.main.name', {
'service.attributes.main.author', query_string: {
'service.attributes.additionalInformation.description' query: `${modifiedSearchTerm}`,
], fields: [
default_operator: 'AND' 'id',
'publicKey.owner',
'dataToken',
'dataTokenInfo.name',
'dataTokenInfo.symbol',
'service.attributes.main.name^10',
'service.attributes.main.author',
'service.attributes.additionalInformation.description',
'service.attributes.additionalInformation.tags'
],
minimum_should_match: '2<75%',
phrase_slop: 2,
boost: 5
}
},
{
match_phrase: {
content: {
query: `${searchTerm}`,
boost: 10
}
}
},
{
query_string: {
query: `${prefixedSearchTerm}`,
fields: [
'id',
'publicKey.owner',
'dataToken',
'dataTokenInfo.name',
'dataTokenInfo.symbol',
'service.attributes.main.name',
'service.attributes.main.author',
'service.attributes.additionalInformation.description',
'service.attributes.additionalInformation.tags'
],
default_operator: 'AND'
}
}
]
}
},
{
term: {
isInPurgatory: false
}
}
]
} }
// ...(owner && { 'publicKey.owner': [owner] }),
// ...(tags && { tags: [tags] }),
// ...(categories && { categories: [categories] })
}, },
sort: { sort: {
[sortTerm]: sortValue [sortTerm]: sortValue
} }
// Something in ocean.js is weird when using 'tags: [tag]'
// which is the only way the query actually returns desired results.
// But it doesn't follow 'SearchQuery' interface so we have to assign
// it here.
// } as SearchQuery
// And the next hack,
// nativeSearch is not implmeneted on ocean.js typings
} }
} }
@ -123,9 +169,9 @@ export async function getResults(
text, text,
owner, owner,
tags, tags,
categories,
page, page,
offset, offset,
categories,
sort, sort,
sortOrder, sortOrder,
serviceType serviceType
@ -143,25 +189,20 @@ export async function getResults(
sortOrder, sortOrder,
serviceType serviceType
) )
const queryResult = await metadataCache.queryMetadata(searchQuery) const queryResult = await metadataCache.queryMetadata(searchQuery)
return queryResult return queryResult
} }
export async function addExistingParamsToUrl( export async function addExistingParamsToUrl(
location: Location, location: Location,
excludedParam: string, excludedParams: string[]
secondExcludedParam?: string
): Promise<string> { ): Promise<string> {
const parsed = queryString.parse(location.search) const parsed = queryString.parse(location.search)
let urlLocation = '/search?' let urlLocation = '/search?'
if (Object.keys(parsed).length > 0) { if (Object.keys(parsed).length > 0) {
for (const querryParam in parsed) { for (const querryParam in parsed) {
if ( if (!excludedParams.includes(querryParam)) {
querryParam !== excludedParam && if (querryParam === 'page' && excludedParams.includes('text')) {
querryParam !== secondExcludedParam
) {
if (querryParam === 'page' && excludedParam === 'text') {
Logger.log('remove page when starting a new search') Logger.log('remove page when starting a new search')
} else { } else {
const value = parsed[querryParam] const value = parsed[querryParam]
@ -170,7 +211,10 @@ export async function addExistingParamsToUrl(
} }
} }
} else { } else {
urlLocation = `${urlLocation}sort=${SortTermOptions.Created}&sortOrder=${SortValueOptions.Descending}&` // sort should be relevance when fixed in aqua
urlLocation = `${urlLocation}sort=${encodeURIComponent(
SortTermOptions.Created
)}&sortOrder=${SortValueOptions.Descending}&`
} }
urlLocation = urlLocation.slice(0, -1) urlLocation = urlLocation.slice(0, -1)
return urlLocation return urlLocation