@axiosleo/orm-mysql 0.14.4 → 0.15.1
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/README.md +57 -416
- package/bin/orm-mysql.js +1 -1
- package/commands/skills.js +223 -0
- package/package.json +1 -1
- package/skills/SKILL.md +159 -0
- package/skills/crud-operations.md +225 -0
- package/skills/pagination.md +301 -0
- package/skills/query-building.md +159 -0
- package/skills/transactions.md +171 -0
- package/skills/where-conditions.md +190 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Where Conditions
|
|
2
|
+
|
|
3
|
+
The `QueryCondition` class provides all WHERE clause methods. All methods return `this` for chaining.
|
|
4
|
+
|
|
5
|
+
## Basic where()
|
|
6
|
+
|
|
7
|
+
### Key-value equality
|
|
8
|
+
|
|
9
|
+
```javascript
|
|
10
|
+
query.where("name", "Joe"); // WHERE `name` = ?
|
|
11
|
+
query.where("age", ">", 18); // WHERE `age` > ?
|
|
12
|
+
query.where("status", "!=", "banned"); // WHERE `status` != ?
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### Object form (multiple equalities)
|
|
16
|
+
|
|
17
|
+
```javascript
|
|
18
|
+
query.where({ name: "Joe", status: "active" });
|
|
19
|
+
// WHERE `name` = ? AND `status` = ?
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Supported operators
|
|
23
|
+
|
|
24
|
+
`=`, `!=`, `>`, `<`, `>=`, `<=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `BETWEEN`, `NOT BETWEEN`, `IS`, `IS NOT`, `REGEXP`, `NOT REGEXP`, `CONTAIN`, `NOT CONTAIN`, `OVERLAPS`, `NOT OVERLAPS`
|
|
25
|
+
|
|
26
|
+
## Logical Operators
|
|
27
|
+
|
|
28
|
+
### AND / OR grouping
|
|
29
|
+
|
|
30
|
+
```javascript
|
|
31
|
+
// Switch to OR logic for subsequent conditions
|
|
32
|
+
query.where("OR");
|
|
33
|
+
// or equivalently:
|
|
34
|
+
query.whereOr();
|
|
35
|
+
|
|
36
|
+
// Switch back to AND logic
|
|
37
|
+
query.where("AND");
|
|
38
|
+
// or equivalently:
|
|
39
|
+
query.whereAnd();
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Combining AND/OR
|
|
43
|
+
|
|
44
|
+
```javascript
|
|
45
|
+
// WHERE `status` = ? AND (`age` > ? OR `vip` = ?)
|
|
46
|
+
query
|
|
47
|
+
.where("status", "active")
|
|
48
|
+
.whereOr()
|
|
49
|
+
.where("age", ">", 18)
|
|
50
|
+
.where("vip", true)
|
|
51
|
+
.whereAnd();
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## IN / NOT IN
|
|
55
|
+
|
|
56
|
+
```javascript
|
|
57
|
+
query.whereIn("status", ["active", "pending"]);
|
|
58
|
+
// WHERE `status` IN (?, ?)
|
|
59
|
+
|
|
60
|
+
query.whereNotIn("role", ["banned", "suspended"]);
|
|
61
|
+
// WHERE `role` NOT IN (?, ?)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Sub-query in whereIn
|
|
65
|
+
|
|
66
|
+
```javascript
|
|
67
|
+
const { Query } = require("@axiosleo/orm-mysql");
|
|
68
|
+
|
|
69
|
+
const subQuery = new Query("select");
|
|
70
|
+
subQuery.table("orders").attr("user_id").where("total", ">", 100);
|
|
71
|
+
|
|
72
|
+
query.whereIn("id", subQuery);
|
|
73
|
+
// WHERE `id` IN (SELECT `user_id` FROM `orders` WHERE `total` > ?)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## LIKE / NOT LIKE
|
|
77
|
+
|
|
78
|
+
```javascript
|
|
79
|
+
query.whereLike("name", "%Joe%");
|
|
80
|
+
// WHERE `name` LIKE ?
|
|
81
|
+
|
|
82
|
+
query.whereNotLike("email", "%spam%");
|
|
83
|
+
|
|
84
|
+
// Multiple patterns (OR)
|
|
85
|
+
query.whereLike("name", ["%Joe%", "%Jane%"]);
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## BETWEEN / NOT BETWEEN
|
|
89
|
+
|
|
90
|
+
```javascript
|
|
91
|
+
query.whereBetween("age", [18, 65]);
|
|
92
|
+
// WHERE `age` BETWEEN ? AND ?
|
|
93
|
+
|
|
94
|
+
query.whereNotBetween("created_at", ["2024-01-01", "2024-06-30"]);
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## CONTAIN / NOT CONTAIN
|
|
98
|
+
|
|
99
|
+
For JSON array or SET column checks:
|
|
100
|
+
|
|
101
|
+
```javascript
|
|
102
|
+
query.whereContain("tags", "javascript");
|
|
103
|
+
// WHERE JSON_CONTAINS(`tags`, ?)
|
|
104
|
+
|
|
105
|
+
query.whereNotContain("tags", "deprecated");
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## OVERLAPS / NOT OVERLAPS
|
|
109
|
+
|
|
110
|
+
For JSON array overlap checks:
|
|
111
|
+
|
|
112
|
+
```javascript
|
|
113
|
+
query.whereOverlaps("categories", [1, 2, 3]);
|
|
114
|
+
|
|
115
|
+
query.whereNotOverlaps("categories", [4, 5]);
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Nested Conditions with whereCondition()
|
|
119
|
+
|
|
120
|
+
Use `QueryCondition` to build complex nested conditions:
|
|
121
|
+
|
|
122
|
+
```javascript
|
|
123
|
+
const { QueryCondition } = require("@axiosleo/orm-mysql");
|
|
124
|
+
|
|
125
|
+
const nested = new QueryCondition();
|
|
126
|
+
nested.where("age", ">", 18).where("age", "<", 65);
|
|
127
|
+
|
|
128
|
+
query
|
|
129
|
+
.where("status", "active")
|
|
130
|
+
.whereCondition(nested);
|
|
131
|
+
// WHERE `status` = ? AND (`age` > ? AND `age` < ?)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Default Joining Between Multiple `whereCondition()` Calls
|
|
135
|
+
|
|
136
|
+
Each `whereCondition()` call appends one parenthesized group to `WHERE`, joined to whatever came before with **`AND`**. There is no implicit `OR` between groups.
|
|
137
|
+
|
|
138
|
+
```javascript
|
|
139
|
+
const g1 = new QueryCondition();
|
|
140
|
+
g1.where("a", 1).whereOr().where("b", 2);
|
|
141
|
+
|
|
142
|
+
const g2 = new QueryCondition();
|
|
143
|
+
g2.where("c", 3).whereOr().where("d", 4);
|
|
144
|
+
|
|
145
|
+
query.where("status", "active")
|
|
146
|
+
.whereCondition(g1)
|
|
147
|
+
.whereCondition(g2);
|
|
148
|
+
// WHERE `status` = ? AND (`a` = ? OR `b` = ?) AND (`c` = ? OR `d` = ?)
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Combining Multiple Groups with `OR`: Wrap, Don't Sprinkle
|
|
152
|
+
|
|
153
|
+
To `OR` two groups together, do **not** insert a top-level `whereOr()` between them on the main builder. SQL evaluates `AND` before `OR`, so the surrounding filters silently bind only to the first group:
|
|
154
|
+
|
|
155
|
+
```javascript
|
|
156
|
+
// BAD -- generates: WHERE `status` = ? AND (`a` = ? OR `b` = ?) OR (`c` = ? OR `d` = ?)
|
|
157
|
+
// `status` = ? only constrains the first group. The second group OR's against everything.
|
|
158
|
+
query.where("status", "active")
|
|
159
|
+
.whereCondition(g1)
|
|
160
|
+
.whereOr()
|
|
161
|
+
.whereCondition(g2);
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Instead, build a single outer `QueryCondition` containing the `OR`'d groups, then attach it once:
|
|
165
|
+
|
|
166
|
+
```javascript
|
|
167
|
+
// GOOD -- generates: WHERE `status` = ? AND ((`a` = ? OR `b` = ?) OR (`c` = ? OR `d` = ?))
|
|
168
|
+
const outer = new QueryCondition();
|
|
169
|
+
outer.whereCondition(g1).whereOr().whereCondition(g2);
|
|
170
|
+
|
|
171
|
+
query.where("status", "active").whereCondition(outer);
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Rule of thumb: `whereOr()` between two `whereCondition()` calls is safe **inside** a `QueryCondition` (it only changes that group's internal logic), but at the top level of the main query builder it leaks the `OR` past your other `AND` filters.
|
|
175
|
+
|
|
176
|
+
When the clauses you want to `OR` together are programmatically generated and share the same shape (e.g. an N-keyword fuzzy search across the same columns), skip the nested `g1`/`g2` and pour every clause directly into a single `QueryCondition` using its own `where()`/`whereOr()` calls -- then attach it to the main builder once. See [pagination.md](pagination.md) (Multi-Keyword Fuzzy Search) for the exact pattern.
|
|
177
|
+
|
|
178
|
+
## Complete Example
|
|
179
|
+
|
|
180
|
+
```javascript
|
|
181
|
+
const results = await db.table("products", "p")
|
|
182
|
+
.where("p.status", "active")
|
|
183
|
+
.whereBetween("p.price", [10, 100])
|
|
184
|
+
.whereIn("p.category_id", [1, 2, 3])
|
|
185
|
+
.whereLike("p.name", "%phone%")
|
|
186
|
+
.whereNotIn("p.id", blockedIds)
|
|
187
|
+
.orderBy("p.price", "asc")
|
|
188
|
+
.page(20, 0)
|
|
189
|
+
.select();
|
|
190
|
+
```
|