@prisma/orm-mongo 8.0.0-rc.11-dev.37 → 8.0.0-rc.11-dev.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma/orm-mongo",
|
|
3
|
-
"version": "8.0.0-rc.11-dev.
|
|
3
|
+
"version": "8.0.0-rc.11-dev.39",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -10,16 +10,16 @@
|
|
|
10
10
|
"skills"
|
|
11
11
|
],
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@prisma/orm-family-mongo": "8.0.0-rc.11-dev.
|
|
14
|
-
"@prisma/orm-framework": "8.0.0-rc.11-dev.
|
|
15
|
-
"@prisma/orm-target-mongo": "8.0.0-rc.11-dev.
|
|
16
|
-
"@prisma/orm-toolchain": "8.0.0-rc.11-dev.
|
|
13
|
+
"@prisma/orm-family-mongo": "8.0.0-rc.11-dev.39",
|
|
14
|
+
"@prisma/orm-framework": "8.0.0-rc.11-dev.39",
|
|
15
|
+
"@prisma/orm-target-mongo": "8.0.0-rc.11-dev.39",
|
|
16
|
+
"@prisma/orm-toolchain": "8.0.0-rc.11-dev.39",
|
|
17
17
|
"pathe": "^2.0.3"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
|
-
"@internal/mongo": "8.0.0-rc.11-dev.
|
|
21
|
-
"@repo/tsconfig": "8.0.0-rc.11-dev.
|
|
22
|
-
"@repo/tsdown": "8.0.0-rc.11-dev.
|
|
20
|
+
"@internal/mongo": "8.0.0-rc.11-dev.39",
|
|
21
|
+
"@repo/tsconfig": "8.0.0-rc.11-dev.39",
|
|
22
|
+
"@repo/tsdown": "8.0.0-rc.11-dev.39",
|
|
23
23
|
"tsdown": "0.22.14",
|
|
24
24
|
"typescript": "5.9.3"
|
|
25
25
|
},
|
package/skills/prisma-8/SKILL.md
CHANGED
|
@@ -126,6 +126,16 @@ Then run `pnpm prisma contract emit` (or rely on the Vite plugin — see `refere
|
|
|
126
126
|
|
|
127
127
|
`name:` declares a wire-named index (physical name `<name>_<8-hex hash>`, renames plan as `ALTER INDEX … RENAME`); `map:` adopts an exact physical name verbatim (for infer-captured objects — combining it with a SQL body warns, because drift detection byte-compares the authored text against Postgres's reprint). An `expression:` requires `name:` or `map:`. The TS builder mirrors this via `constraints.index([cols.x], {...})` / `constraints.index({ expression, ... })` — see `packages/2-sql/2-authoring/contract-ts/README.md`.
|
|
128
128
|
|
|
129
|
+
**Full-text search indexes (PostgreSQL).** Do not hand-write the `to_tsvector` expression — Postgres only uses the index when it is the same `to_tsvector` over the same configuration literal and the same column as the query. Declare `@@fullTextIndex`, which renders the same expression `fullTextMatches` / `fullTextRank` / `fullTextHeadline` lower to (see `references/queries-postgres.md`):
|
|
130
|
+
|
|
131
|
+
```prisma
|
|
132
|
+
@@fullTextIndex([text], name: "message_text_search")
|
|
133
|
+
@@fullTextIndex([summary], language: "german", name: "message_summary_search_de")
|
|
134
|
+
@@fullTextIndex([text], where: "archived_at IS NULL", name: "message_text_search_live")
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
The TS builder has the same helper: `fullTextIndex(cols.text, { name: 'message_text_search' })`, from `@prisma/orm-postgres/contract-builder`, inside the model's `sql({ indexes: [...] })`. It takes exactly one field, an optional `language` (default `english`, from the same allowlist the operations accept), an optional `where:` for a partial index, and `name:` xor `map:` like any expression index. It is repeatable, so a model may index several columns. Give the index and the operation the same `language` — a mismatch is silent, costing the index and falling back to a sequential scan. It lowers to a GIN index over `to_tsvector('<language>', "<column>")` — the column name resolved through `@map` — so `@@index(expression: …)` remains only for expressions this attribute does not cover.
|
|
138
|
+
|
|
129
139
|
PSL alias surface for repeated types lives in a top-level `types {}` block:
|
|
130
140
|
|
|
131
141
|
```prisma
|
|
@@ -62,6 +62,44 @@ db.orm.public.User.where({ kind: 'admin' });
|
|
|
62
62
|
|
|
63
63
|
Operators on the field proxy include `.eq`, `.neq`, `.lt`, `.lte`, `.gt`, `.gte`, `.like`, `.ilike`, `.in([...])`, `.isNull()`, `.isNotNull()`. Extensions add target-specific operators on extension-typed columns (`pgvector`'s `.cosineDistance(...)`, `postgis`'s `.within(...)` / `.intersectsBbox(...)` / `.distanceSphere(...)`).
|
|
64
64
|
|
|
65
|
+
**Full-text search** is built into the Postgres target, on any text column: `.fullTextMatches(q)` is the predicate, `.fullTextRank(q)` scores a row so you can order by relevance, and `.fullTextHeadline(q)` returns the text with `<b>` around the matches. The search string is a bound parameter lowered to `websearch_to_tsquery`, so `"an exact phrase"` and `-excluded` work the way a user expects from a search box. Each takes an options object as its second argument. `language` defaults to `'english'` and only accepts the configurations a stock PostgreSQL server ships with (`'simple'`, `'german'`, `'french'`, …); `fullTextRank` also takes `normalization` (the `ts_rank` bitmask, 0 to 63) and `coverDensity` (for `ts_rank_cd`); `fullTextHeadline` also takes `startSel`, `stopSel`, `maxWords`, `minWords` and `highlightAll`. Every one of them is written into the SQL as a literal, so anything invalid throws `RUNTIME.ARGUMENT_INVALID` when the query is built.
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
// ORM: filter by the query, order by relevance.
|
|
69
|
+
const hits = await db.orm.public.Message
|
|
70
|
+
.select('id', 'text')
|
|
71
|
+
.where((m) => m.text.fullTextMatches(query))
|
|
72
|
+
.orderBy((m) => m.text.fullTextRank(query).desc())
|
|
73
|
+
.limit(20)
|
|
74
|
+
.all();
|
|
75
|
+
|
|
76
|
+
// SQL builder: the same predicate, plus a snippet with your own markers.
|
|
77
|
+
const snippets = db.sql.public.message
|
|
78
|
+
.select('id')
|
|
79
|
+
.select('snippet', (f, fns) =>
|
|
80
|
+
fns.fullTextHeadline(f.text, query, { startSel: '<mark>', stopSel: '</mark>', maxWords: 20 }),
|
|
81
|
+
)
|
|
82
|
+
.where((f, fns) => fns.fullTextMatches(f.text, query))
|
|
83
|
+
.build();
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Without an index Postgres recomputes `to_tsvector` for every row, and it only uses one whose expression is the same `to_tsvector` over the same configuration literal and the same column. `@@fullTextIndex` renders that expression for you — pass it the field and, if you use one, the same language:
|
|
87
|
+
|
|
88
|
+
```prisma
|
|
89
|
+
@@fullTextIndex([text], name: "message_text_search")
|
|
90
|
+
@@fullTextIndex([text], where: "archived_at IS NULL", name: "message_text_search_live")
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Give the index and the operation the same `language`: a mismatch raises no error, the query silently falls back to a sequential scan.
|
|
94
|
+
|
|
95
|
+
In a TypeScript contract, the same helper from `@prisma/orm-postgres/contract-builder`:
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
model('Message', { fields: { id, text } }).sql(({ cols }) => ({
|
|
99
|
+
indexes: [fullTextIndex(cols.text, { name: 'message_text_search' })],
|
|
100
|
+
}));
|
|
101
|
+
```
|
|
102
|
+
|
|
65
103
|
**There is no `.between(a, b)` operator.** Express ranges either as two chained `.where(...)` clauses (the idiomatic form — clauses AND-compose) or with the `and(...)` combinator inside one clause:
|
|
66
104
|
|
|
67
105
|
```typescript
|