Skip to content

Commit

Permalink
feat(core): add new search config API (#5948)
Browse files Browse the repository at this point in the history
* feat(core): implement new search configuration

---

Co-authored-by: Ash <[email protected]>

* chore(core): deprecate `__experimental_search`

---

Co-authored-by: Ash <[email protected]>

* chore(test-studio): update author w/ new search config

---

Co-authored-by: Ash <[email protected]>

* test(core): add `createTextSearch` tests

---------

Co-authored-by: Rico Kahler <[email protected]>
  • Loading branch information
juice49 and ricokahler authored Mar 12, 2024
1 parent 193b4b8 commit 3c458c8
Show file tree
Hide file tree
Showing 40 changed files with 1,155 additions and 424 deletions.
15 changes: 8 additions & 7 deletions dev/test-studio/schema/author.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import {UserIcon as icon} from '@sanity/icons'
import {type Rule} from 'sanity'
import {defineField, defineType, type Rule} from 'sanity'

const AUTHOR_ROLES = [
{value: 'developer', title: 'Developer'},
{value: 'designer', title: 'Designer'},
{value: 'ops', title: 'Operations'},
]

export default {
export default defineType({
name: 'author',
type: 'document',
title: 'Author',
icon,
description: 'This represents an author',
// eslint-disable-next-line camelcase
__experimental_search: [{path: 'name', weight: 10}],
preview: {
select: {
title: 'name',
Expand All @@ -36,12 +34,15 @@ export default {
},
},
fields: [
{
defineField({
name: 'name',
title: 'Name',
type: 'string',
options: {
search: {weight: 100},
},
validation: (rule: Rule) => rule.required(),
},
}),
{
name: 'bestFriend',
title: 'Best friend',
Expand Down Expand Up @@ -125,4 +126,4 @@ export default {
},
},
}),
}
})
2 changes: 1 addition & 1 deletion packages/@sanity/types/src/crossDatasetReference/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export interface CrossDatasetType {
title?: string
icon: ComponentType
preview: PreviewConfig
/** @alpha */
/** @deprecated Unused. Configuring search is no longer supported for cross-dataset references. */
__experimental_search: ObjectSchemaType['__experimental_search']
}

Expand Down
4 changes: 2 additions & 2 deletions packages/@sanity/types/src/schema/definition/type/array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import {
type IntrinsicTypeName,
type TypeAliasDefinition,
} from '../schemaDefinition'
import {type BaseSchemaDefinition, type TitledListValue} from './common'
import {type BaseSchemaDefinition, type SearchConfiguration, type TitledListValue} from './common'

/** @public */
export interface ArrayOptions<V = unknown> {
export interface ArrayOptions<V = unknown> extends SearchConfiguration {
list?: TitledListValue<V>[] | V[]
/**
* layout: 'tags' only works for string array
Expand Down
21 changes: 21 additions & 0 deletions packages/@sanity/types/src/schema/definition/type/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,24 @@ export interface EnumListProps<V = unknown> {
layout?: 'radio' | 'dropdown'
direction?: 'horizontal' | 'vertical'
}

/** @public */
export interface SearchConfiguration {
search?: {
/**
* Defines a search weight for this field to prioritize its importance
* during search operations in the Studio. This setting allows the specified
* field to be ranked higher in search results compared to other fields.
*
* By default, all fields are assigned a weight of 1. However, if a field is
* chosen as the `title` in the preview configuration's `select` option, it
* will automatically receive a default weight of 10. Similarly, if selected
* as the `subtitle`, the default weight is 5. Fields marked as
* `hidden: true` (no function) are assigned a weight of 0 by default.
*
* Note: Search weight configuration is currently supported only for fields
* of type string or portable text arrays.
*/
weight?: number
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export interface CrossDatasetReferenceDefinition extends BaseSchemaDefinition {
preview?: PreviewConfig

/**
* @deprecated Configuring search is no longer supported
* @deprecated Unused. Configuring search is no longer supported.
*/
__experimental_search?: {path: string | string[]; weight?: number; mapWith?: string}[]
}[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export interface DocumentDefinition extends Omit<ObjectDefinition, 'type'> {
options?: DocumentOptions
validation?: ValidationBuilder<DocumentRule, SanityDocument>
initialValue?: InitialValueProperty<any, Record<string, unknown>>
/** @alpha */
/** @deprecated Unused. Use the new field-level search config. */
__experimental_search?: {path: string; weight: number; mapWith?: string}[]
/** @alpha */
__experimental_omnisearch_visibility?: boolean
Expand Down
4 changes: 2 additions & 2 deletions packages/@sanity/types/src/schema/definition/type/string.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {type FieldReference} from '../../../validation'
import {type RuleDef, type ValidationBuilder} from '../../ruleBuilder'
import {type InitialValueProperty} from '../../types'
import {type BaseSchemaDefinition, type EnumListProps} from './common'
import {type BaseSchemaDefinition, type EnumListProps, type SearchConfiguration} from './common'

/** @public */
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface StringOptions extends EnumListProps<string> {}
export interface StringOptions extends EnumListProps<string>, SearchConfiguration {}

/** @public */
export interface StringRule extends RuleDef<StringRule, string> {
Expand Down
2 changes: 1 addition & 1 deletion packages/@sanity/types/src/schema/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ export interface ObjectSchemaType extends BaseSchemaType {
// Note: `path` is a string in the _specification_, but converted to a
// string/number array in the schema normalization/compilation step
// a path segment is a number when specified like array.0.prop in preview config.
/** @alpha */
/** @deprecated Unused. Use the new field-level search config. */
__experimental_search: {path: (string | number)[]; weight: number; mapWith?: string}[]
/** @alpha */
__experimental_omnisearch_visibility?: boolean
Expand Down
2 changes: 1 addition & 1 deletion packages/sanity/src/_internal/browser.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export {createSearch, getSearchableTypes, getSearchTypesWithMaxDepth} from '../core/search'
export {createSearch, getSearchableTypes} from '../core/search'
export {useSearchMaxFieldDepth} from '../core/studio/components/navbar/search/hooks/useSearchMaxFieldDepth'
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import {type SanityClient} from '@sanity/client'
import {DEFAULT_MAX_FIELD_DEPTH} from '@sanity/schema/_internal'
import {type ReferenceFilterSearchOptions, type ReferenceSchemaType} from '@sanity/types'
import {combineLatest, type Observable, of} from 'rxjs'
import {map, mergeMap, startWith, switchMap} from 'rxjs/operators'

import {type DocumentPreviewStore, getPreviewPaths, prepareForPreview} from '../../../../preview'
import {createSearch, getSearchTypesWithMaxDepth} from '../../../../search'
import {createSearch} from '../../../../search'
import {collate, type CollatedHit, getDraftId, getIdPair, isRecord} from '../../../../util'
import {type ReferenceInfo, type ReferenceSearchHit} from '../../../inputs/ReferenceInput/types'

Expand Down Expand Up @@ -193,9 +194,10 @@ export function referenceSearch(
options: ReferenceFilterSearchOptions,
unstable_enableNewSearch: boolean,
): Observable<ReferenceSearchHit[]> {
const search = createSearch(getSearchTypesWithMaxDepth(type.to, options.maxFieldDepth), client, {
const search = createSearch(type.to, client, {
...options,
unstable_enableNewSearch,
maxDepth: options.maxFieldDepth || DEFAULT_MAX_FIELD_DEPTH,
})
return search(textTerm, {includeDrafts: true}).pipe(
map(({hits}) => hits.map(({hit}) => hit)),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {type SanityClient} from '@sanity/client'
import {resolveSearchConfigForBaseFieldPaths} from '@sanity/schema/_internal'
import {
type CrossDatasetReferenceSchemaType,
type ReferenceFilterSearchOptions,
Expand All @@ -22,20 +21,15 @@ export function search(
type: CrossDatasetReferenceSchemaType,
options: ReferenceFilterSearchOptions,
): Observable<SearchHit[]> {
const searchWeighted = createSearch(
type.to.map((crossDatasetType) => ({
name: crossDatasetType.type,
// eslint-disable-next-line camelcase
__experimental_search: resolveSearchConfigForBaseFieldPaths(
crossDatasetType,
options.maxFieldDepth,
),
})),
client,
options,
)
const searchStrategy = createSearch(type.to, client, {
...options,
maxDepth: options.maxFieldDepth,
})

return searchWeighted(textTerm, {includeDrafts: false}).pipe(
return searchStrategy(textTerm, {
includeDrafts: false,
isCrossDataset: true,
}).pipe(
map(({hits}) => hits.map(({hit}) => hit)),
map(collate),
map((collated) =>
Expand Down
8 changes: 1 addition & 7 deletions packages/sanity/src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,7 @@ export * from './i18n'
export * from './presence'
export * from './preview'
export * from './schema'
export type {
SearchableType,
SearchFactoryOptions,
SearchOptions,
SearchSort,
SearchTerms,
} from './search'
export type {SearchFactoryOptions, SearchOptions, SearchSort, SearchTerms} from './search'
export * from './store'
export * from './studio'
export * from './studioClient'
Expand Down
Loading

0 comments on commit 3c458c8

Please sign in to comment.