-
Notifications
You must be signed in to change notification settings - Fork 392
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move search logic into parts (#1105)
* [base] Move search logic into parts * [base] Add quard for supporting queries without terms * [base] Add support for search options * [default-layout] Pass search options
- Loading branch information
1 parent
3d2abf6
commit 87a49db
Showing
8 changed files
with
145 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import {flow, compact, flatten, union, uniq} from 'lodash' | ||
import client from 'part:@sanity/base/client?' | ||
import schema from 'part:@sanity/base/schema?' | ||
import { | ||
escapeField, | ||
fieldNeedsEscape, | ||
getSearchableTypeNames, | ||
joinPath | ||
} from 'part:@sanity/base/util/search-utils' | ||
|
||
const combineFields = flow([flatten, union, compact]) | ||
|
||
function mapToEscapedProjectionFieldName(fieldName) { | ||
if (fieldNeedsEscape(fieldName)) return `"${fieldName}":${escapeField(fieldName)}` | ||
|
||
return fieldName | ||
} | ||
|
||
function fetchSearchResults(query, opts = {}) { | ||
if (!client) throw new Error('Sanity client is missing') | ||
|
||
const typeNames = opts.types || getSearchableTypeNames() | ||
const types = typeNames.map(typeName => schema.get(typeName)) | ||
|
||
const groqParams = query.terms.reduce( | ||
(acc, term, i) => { | ||
acc[`t${i}`] = `${term}*` // "t" is short for term | ||
return acc | ||
}, | ||
{ | ||
limit: opts.limit || 100 | ||
} | ||
) | ||
|
||
const groqFilters = query.groqFilters ? query.groqFilters.slice(0) : [] | ||
|
||
const uniqueFields = combineFields( | ||
types.map(type => (type.__unstable_searchFields || []).map(joinPath)) | ||
) | ||
|
||
const constraints = query.terms.map((term, i) => | ||
uniqueFields.map(joinedPath => `${joinedPath} match $t${i}`) | ||
) | ||
|
||
if (constraints.length) { | ||
groqFilters.push(constraints.map(constraint => `(${constraint.join('||')})`).join('&&')) | ||
} | ||
|
||
const groqFilterString = `(${groqFilters.join(')&&(')})` | ||
|
||
const fields = uniq(['_id', '_type'].concat(opts.fields || [])).map( | ||
mapToEscapedProjectionFieldName | ||
) | ||
|
||
const groqQuery = `*[${groqFilterString}][0...$limit]{${fields.join(',')}}` | ||
|
||
return client.observable.fetch(groqQuery, groqParams) | ||
} | ||
|
||
export default fetchSearchResults |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import fetchSearchResults from 'part:@sanity/base/search/fetchSearchResults' | ||
import parseSearchQuery from 'part:@sanity/base/search/parseSearchQuery' | ||
import prepareSearchResults from 'part:@sanity/base/search/prepareSearchResults' | ||
import {map} from 'rxjs/operators' | ||
|
||
function search(queryStr, opts) { | ||
const query = parseSearchQuery(queryStr, opts) | ||
|
||
return fetchSearchResults(query, opts).pipe( | ||
map(results => prepareSearchResults(results, query, opts)) | ||
) | ||
} | ||
|
||
export default search |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
function parseSearchQuery(queryStr, opts = {}) { | ||
const terms = queryStr.split(/\s+/).filter(Boolean) | ||
|
||
return { | ||
original: queryStr, | ||
terms, | ||
groqFilters: [] | ||
} | ||
} | ||
|
||
export default parseSearchQuery |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
function prepareSearchResults(results, query, opts = {}) { | ||
// This function may be extended by overriding using the part system | ||
return results | ||
} | ||
|
||
export default prepareSearchResults |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters