search-assets
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseImageKit Search Queries (searchQuery
)
searchQueryImageKit 搜索查询(searchQuery
)
searchQueryclient.assets.list({ searchQuery })When user requests "find Nike brand images", here brand could be a custom metadata field, i.e. . So it is always recommended to first list the custom metadata fields available so that correct can be constructed. You can use to get the list of custom metadata fields and their types.
"customMetadata.brand"searchQueryclient.customMetadataFields.list()client.assets.list({ searchQuery })当用户请求“查找Nike品牌图片”时,这里的“brand”可能是一个自定义元数字段,即 。因此,始终建议先列出可用的自定义元数字段,以便构建正确的。你可以使用获取自定义元数字段列表及其类型。
"customMetadata.brand"searchQueryclient.customMetadataFields.list()Syntax
语法
- Operators:
=:<<=>>=INNOT INNOT =HASEXISTSNOT EXISTS - Combine: ,
AND. Group:OR( ... ) - Quoting: string values in ; numbers and booleans (
"double quotes"/true) unquoted;false/customMetadatafield names must be quoted, e.g.embeddedMetadata."customMetadata.brand" - = begins-with / within-subfolders.
:= exact.== case-insensitive full-text (tokenized).HAS
- 运算符:
=:<<=>>=INNOT INNOT =HASEXISTSNOT EXISTS - 组合: 、
AND。分组:OR( ... ) - 引号规则: 字符串值需用包裹;数字和布尔值(
"双引号"/true)无需引号;false/customMetadata字段名必须加引号,例如embeddedMetadata。"customMetadata.brand" - = 前缀匹配/包含子文件夹。
:= 精确匹配。== 不区分大小写的全文(分词)匹配。HAS
Field reference
字段参考
| Field | Operators | Value notes |
|---|---|---|
| | String. |
| | Array. Matches both |
| | |
| | fileId or folderId string |
| | ISO 8601 ( |
| | Numeric px. Images only |
| | Bytes ( |
| | |
| | Boolean, unquoted: |
| | Uploader email string |
| | |
| type-dependent ( | Quote the field name. Operators follow the field's schema type |
| type-dependent | Quote the field name. |
| 字段 | 运算符 | 值说明 |
|---|---|---|
| | 字符串。 |
| | 数组。同时匹配 |
| | |
| | 文件ID或文件夹ID字符串 |
| | ISO 8601格式( |
| | 数值(像素)。仅适用于图片 |
| | 字节数( |
| | |
| | 布尔值,无需引号: |
| | 上传者邮箱字符串 |
| | |
| 依赖类型( | 字段名需加引号。运算符遵循字段的 schema 类型 |
| 依赖类型 | 字段名需加引号。 |
Query examples
查询示例
text
name = "red-dress.jpg" exact name (case-sensitive)
name : "red-dress" name begins with red-dress
name HAS "red dress" full-text: contains red AND dress (any case)
id = "64fb1c2d8a7b4c1234567890" single file/folder by id
createdAt > "7d" uploaded in last 7 days
createdAt < 2020-01-01 uploaded before Jan 1 2020 (00:00 UTC)
updatedAt >= "2024-06-01T00:00:00" modified on/after a timestamp
createdAt > "7d" AND size > "2mb" recent AND large
size <= "1mb" 1MB or smaller
width > 500 AND height > 500 at least 500x500 (images)
format = "png" PNG files
format IN ["jpg", "webp"] JPG or WebP
tags IN ["sale", "summer"] has sale OR summer (tags or AITags)
tags NOT IN ["draft"] excludes draft
tags HAS "sale" full-text token match (sales, summer-sale…)
tags EXISTS has at least one tag
tags NOT EXISTS untagged files
type = "file" files only
private = true private files
published = false drafts / unpublished
transparency = true images with an alpha layer
path = "/sales-banner/" exactly this folder, no subfolders
path : "/sales-banner/" this folder AND its subfolders
format = "png" AND path : "/sales-banner/" PNGs under a folder tree
"customMetadata.category" IN ["clothing", "accessories"]
"customMetadata.rating" > 4.3
"customMetadata.active" = true
"customMetadata.description" HAS "red"
"embeddedMetadata.DateTimeOriginal" > "1y"
"embeddedMetadata.LocationTaken" = "40,100 5km"
(size < "1mb" AND width > 500) OR (tags IN ["summer-sale", "banner"])text
name = "red-dress.jpg" exact name (case-sensitive)
name : "red-dress" name begins with red-dress
name HAS "red dress" full-text: contains red AND dress (any case)
id = "64fb1c2d8a7b4c1234567890" single file/folder by id
createdAt > "7d" uploaded in last 7 days
createdAt < 2020-01-01 uploaded before Jan 1 2020 (00:00 UTC)
updatedAt >= "2024-06-01T00:00:00" modified on/after a timestamp
createdAt > "7d" AND size > "2mb" recent AND large
size <= "1mb" 1MB or smaller
width > 500 AND height > 500 at least 500x500 (images)
format = "png" PNG files
format IN ["jpg", "webp"] JPG or WebP
tags IN ["sale", "summer"] has sale OR summer (tags or AITags)
tags NOT IN ["draft"] excludes draft
tags HAS "sale" full-text token match (sales, summer-sale…)
tags EXISTS has at least one tag
tags NOT EXISTS untagged files
type = "file" files only
private = true private files
published = false drafts / unpublished
transparency = true images with an alpha layer
path = "/sales-banner/" exactly this folder, no subfolders
path : "/sales-banner/" this folder AND its subfolders
format = "png" AND path : "/sales-banner/" PNGs under a folder tree
"customMetadata.category" IN ["clothing", "accessories"]
"customMetadata.rating" > 4.3
"customMetadata.active" = true
"customMetadata.description" HAS "red"
"embeddedMetadata.DateTimeOriginal" > "1y"
"embeddedMetadata.LocationTaken" = "40,100 5km"
(size < "1mb" AND width > 500) OR (tags IN ["summer-sale", "banner"])Custom metadata — discover field names first
自定义元数据——先获取字段名
"customMetadata.<field>"=:INHAS<<=>>==INtypescript
const fields = await client.customMetadataFields.list();
// each: { id, name, label, schema: { type: 'Text' | 'Number' | 'Date' | 'Boolean' | 'SingleSelect' | 'MultiSelect', ... } }
const brand = fields.find((f) => f.name === 'brand' || f.label === 'Brand');
if (!brand) throw new Error('No "brand" custom metadata field is defined');
const result = await client.assets.list({
searchQuery: 'type = "file" AND "customMetadata.brand" = "nike"',
limit: 100,
});Quote the whole token. (e.g. , , ) works the same way, but embedded fields are read from the file itself and are not user-defined — no schema lookup needed.
"customMetadata.<field>""embeddedMetadata.<field>"KeywordsDateTimeOriginalLocationTaken"customMetadata.<field>"=:INHAS<<=>>==INtypescript
const fields = await client.customMetadataFields.list();
// each: { id, name, label, schema: { type: 'Text' | 'Number' | 'Date' | 'Boolean' | 'SingleSelect' | 'MultiSelect', ... } }
const brand = fields.find((f) => f.name === 'brand' || f.label === 'Brand');
if (!brand) throw new Error('No "brand" custom metadata field is defined');
const result = await client.assets.list({
searchQuery: 'type = "file" AND "customMetadata.brand" = "nike"',
limit: 100,
});需将整个标记用引号包裹。(例如、、)的用法相同,但嵌入字段是从文件本身读取的,并非用户定义——无需查找schema。
"customMetadata.<field>""embeddedMetadata.<field>"KeywordsDateTimeOriginalLocationTakenTypeScript usage
TypeScript 使用方法
client.assets.list()(File | Folder)[]searchQueryNo — pass to get a typed array directly (no narrowing):
searchQuerytypetypescript
const files = await client.assets.list({ type: 'file', path: '/uploads', limit: 100 });
// ^ File[] — fileId, size, url are all available without narrowingWith — the API IGNORES the // params, so the result stays the union. Put the type filter inside the query string and narrow each item:
searchQuerytypetagsname(File | Folder)[]typescript
const result = await client.assets.list({
searchQuery: 'type = "file" AND createdAt >= "7d" AND size > "2mb"',
limit: 100,
});
const files = [];
for (const item of result) {
if (item.type === 'file') {
files.push({ name: item.name, fileId: item.fileId, size: item.size });
}
}Accessing ANY member-specific property. On the bare union you can only read properties common to both (, , , , ). Every other property — , , , , , … (File-only) and (Folder-only) — exists on just one member and won't compile until you narrow to a single concrete type. Narrow once with an /, then access anything inside that block. Key subtlety: is while is only , so branch on — its else branch is guaranteed (covers plain files and file-versions):
File | FoldernametypecreatedAtupdatedAtcustomMetadatafilePathurlfileIdsizewidthtagsfolderPathitemifelseFile.type'file' | 'file-version'Folder.type'folder'type === 'folder'Filetypescript
const rows = result.map((item) => {
if (item.type === 'folder') {
return { name: item.name, kind: 'folder', path: item.folderPath }; // item: Folder
}
return { name: item.name, kind: 'file', path: item.filePath, size: item.size, url: item.url }; // item: File
});Only reading File fields? A single guard is enough — inside it is a fully-typed , so any File property is available.
if (item.type === 'file') { … }itemFileFull-text search — always pair with :
HASDESC_RELEVANCEtypescript
const result = await client.assets.list({
searchQuery: 'name HAS "red dress"',
sort: 'DESC_RELEVANCE',
limit: 20,
});Paginate with / (max 1000 per page):
skiplimittypescript
for (let skip = 0; ; skip += 100) {
const page = await client.assets.list({
searchQuery: 'type = "file" AND tags IN ["sale", "summer"]',
skip,
limit: 100,
});
if (!page.length) break;
for (const item of page) {
if (item.type === 'file') {
// item narrowed to File
}
}
}client.assets.list()(File | Folder)[]searchQuery不使用——传入直接获取类型化数组(无需类型收窄):
searchQuerytypetypescript
const files = await client.assets.list({ type: 'file', path: '/uploads', limit: 100 });
// ^ File[] — fileId、size、url等属性无需类型收窄即可访问使用——API会忽略//参数,因此结果仍为联合类型。需将类型过滤条件放入查询字符串中,再对每个条目进行类型收窄:
searchQuerytypetagsname(File | Folder)[]typescript
const result = await client.assets.list({
searchQuery: 'type = "file" AND createdAt >= "7d" AND size > "2mb"',
limit: 100,
});
const files = [];
for (const item of result) {
if (item.type === 'file') {
files.push({ name: item.name, fileId: item.fileId, size: item.size });
}
}访问特定成员的属性。 在联合类型中,只能读取两者共有的属性(、、、、)。其他所有属性——、、、、、…(仅File拥有)和(仅Folder拥有)——仅属于其中一个类型,必须先对进行类型收窄才能编译通过。用/进行一次类型收窄,然后在代码块内访问任意属性。关键细节:为,而仅为,因此通过分支——其else分支必然是(涵盖普通文件和文件版本):
File | FoldernametypecreatedAtupdatedAtcustomMetadatafilePathurlfileIdsizewidthtagsfolderPathitemifelseFile.type'file' | 'file-version'Folder.type'folder'type === 'folder'Filetypescript
const rows = result.map((item) => {
if (item.type === 'folder') {
return { name: item.name, kind: 'folder', path: item.folderPath }; // item: Folder
}
return { name: item.name, kind: 'file', path: item.filePath, size: item.size, url: item.url }; // item: File
});仅需读取File属性?只需即可——代码块内为完全类型化的,可访问任何File属性。
if (item.type === 'file') { … }itemFile全文搜索——务必将与配合使用:
HASDESC_RELEVANCEtypescript
const result = await client.assets.list({
searchQuery: 'name HAS "red dress"',
sort: 'DESC_RELEVANCE',
limit: 20,
});使用/分页(每页最多1000条):
skiplimittypescript
for (let skip = 0; ; skip += 100) {
const page = await client.assets.list({
searchQuery: 'type = "file" AND tags IN ["sale", "summer"]',
skip,
limit: 100,
});
if (!page.length) break;
for (const item of page) {
if (item.type === 'file') {
// item 已收窄为File类型
}
}
}Gotchas
注意事项
- overrides params. When
searchQueryis present, the top-levelsearchQuery,type, andtagsparams have NO effect — express those filters inside the query string instead (e.g.name).type = "file" - Narrow with +
for...of, notif. In the Deno/MCP sandbox the global.filter((i): i is File => ...)(Web API) shadows the SDK'sFiletype, so the type predicate fails to compile. UseFile.for (const item of result) { if (item.type === 'file') { … } } - Only common fields exist on the bare union.
File | Folder,name,type,createdAt,updatedAtare shared; everything else (customMetadata,filePath,url,fileId,size,width,tags…) is member-specific and needs narrowing first. Never reach for a property before narrowing.folderPath - Branch on to split the union cleanly.
type === 'folder'isFile.type;'file' | 'file-version'is onlyFolder.type. So'folder'catches plain files but leaves the else branch astype === 'file', whereasFile | Foldergivestype === 'folder'in theFolderand a guaranteedifin theFile.else name/=are case-sensitive; use:for case-insensitive matching.HAS- queries search both
tagsandtags.AITags - tokenizes on spaces/punctuation; the last token matches as a prefix (
HASmatches"red"). Pair withredwoods.sort: 'DESC_RELEVANCE' - Booleans (,
private,published) are unquoted; everything string-valued is quoted.transparency - /
width/heightapply to images only.transparency
- 会覆盖参数。 当存在
searchQuery时,顶层的searchQuery、type和tags参数无效——需将这些过滤条件放入查询字符串中(例如name)。type = "file" - 使用+
for...of进行类型收窄,而非if。 在Deno/MCP沙箱中,全局.filter((i): i is File => ...)(Web API)会遮蔽SDK的File类型,因此类型断言无法编译。请使用File。for (const item of result) { if (item.type === 'file') { … } } - 仅共有属性存在于联合类型中。
File | Folder、name、type、createdAt、updatedAt是共享属性;其他所有属性(customMetadata、filePath、url、fileId、size、width、tags…)都是特定成员的属性,需要先进行类型收窄。在类型收窄前切勿访问这些属性。folderPath - 通过分支可清晰拆分联合类型。
type === 'folder'为File.type;'file' | 'file-version'仅为Folder.type。因此'folder'仅匹配普通文件,else分支仍为type === 'file',而File | Folder会在type === 'folder'分支得到if,else分支必然是Folder。File - 的
name/=运算符区分大小写;如需不区分大小写匹配,请使用:。HAS - 查询会同时搜索**
tags和tags**。AITags - 会按空格/标点分词;最后一个分词会作为前缀匹配(
HAS会匹配"red")。需配合redwoods使用。sort: 'DESC_RELEVANCE' - 布尔值(、
private、published)无需引号;所有字符串值都需加引号。transparency - /
width/height仅适用于图片。transparency