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:
parent
6ed92c0bfd
commit
eb8c6afb62
2
package-lock.json
generated
2
package-lock.json
generated
@ -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",
|
||||||
|
@ -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`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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}`
|
||||||
|
|
||||||
|
@ -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}>
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user