@thi.ng/oquery 2.2.40 → 2.2.42
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/CHANGELOG.md +8 -1
- package/README.md +2 -2
- package/api.d.ts +17 -8
- package/match.d.ts +42 -29
- package/match.js +3 -6
- package/package.json +12 -12
- package/query.js +131 -136
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**: 2024-
|
|
3
|
+
- **Last updated**: 2024-06-21T19:34:38Z
|
|
4
4
|
- **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
|
|
5
5
|
|
|
6
6
|
All notable changes to this project will be documented in this file.
|
|
@@ -9,6 +9,13 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
|
|
|
9
9
|
**Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
|
|
10
10
|
and/or version bumps of transitive dependencies.
|
|
11
11
|
|
|
12
|
+
### [2.2.42](https://github.com/thi-ng/umbrella/tree/@thi.ng/oquery@2.2.42) (2024-06-21)
|
|
13
|
+
|
|
14
|
+
#### ♻️ Refactoring
|
|
15
|
+
|
|
16
|
+
- enforce uniform naming convention of internal functions ([56992b2](https://github.com/thi-ng/umbrella/commit/56992b2))
|
|
17
|
+
- minor internal restructuring ([3aa9e8b](https://github.com/thi-ng/umbrella/commit/3aa9e8b))
|
|
18
|
+
|
|
12
19
|
### [2.2.26](https://github.com/thi-ng/umbrella/tree/@thi.ng/oquery@2.2.26) (2024-02-22)
|
|
13
20
|
|
|
14
21
|
#### ♻️ Refactoring
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
[](https://mastodon.thi.ng/@toxi)
|
|
8
8
|
|
|
9
9
|
> [!NOTE]
|
|
10
|
-
> This is one of
|
|
10
|
+
> This is one of 193 standalone projects, maintained as part
|
|
11
11
|
> of the [@thi.ng/umbrella](https://github.com/thi-ng/umbrella/) monorepo
|
|
12
12
|
> and anti-framework.
|
|
13
13
|
>
|
|
@@ -89,7 +89,7 @@ For Node.js REPL:
|
|
|
89
89
|
const oq = await import("@thi.ng/oquery");
|
|
90
90
|
```
|
|
91
91
|
|
|
92
|
-
Package sizes (brotli'd, pre-treeshake): ESM: 1.
|
|
92
|
+
Package sizes (brotli'd, pre-treeshake): ESM: 1.69 KB
|
|
93
93
|
|
|
94
94
|
## Dependencies
|
|
95
95
|
|
package/api.d.ts
CHANGED
|
@@ -72,15 +72,19 @@ export interface QueryOpts {
|
|
|
72
72
|
* successfully matched property values will be included for each result.
|
|
73
73
|
*
|
|
74
74
|
* @example
|
|
75
|
-
* ```ts
|
|
75
|
+
* ```ts tangle:../export/def-query.ts
|
|
76
76
|
* import { defQuery } from "@thi.ng/oquery";
|
|
77
77
|
*
|
|
78
78
|
* const DB = { a: { id: 1, name: "alice" }, b: { name: "bob" } };
|
|
79
79
|
*
|
|
80
|
-
*
|
|
80
|
+
* console.log(
|
|
81
|
+
* defQuery({ partial: false })(DB, null, "id", 1)
|
|
82
|
+
* );
|
|
81
83
|
* // { a: { id: 1, name: "alice" } }
|
|
82
84
|
*
|
|
83
|
-
*
|
|
85
|
+
* console.log(
|
|
86
|
+
* defQuery({ partial: true })(DB, null, "id", 1)
|
|
87
|
+
* );
|
|
84
88
|
* // { a: { id: 1 } }
|
|
85
89
|
* ```
|
|
86
90
|
*
|
|
@@ -97,15 +101,20 @@ export interface QueryOpts {
|
|
|
97
101
|
* ALWAYS matched in a componentwise manner.
|
|
98
102
|
*
|
|
99
103
|
* @example
|
|
100
|
-
* ```ts
|
|
104
|
+
* ```ts tangle:../export/def-query-2.ts
|
|
101
105
|
* import { defQuery } from "@thi.ng/oquery";
|
|
102
106
|
*
|
|
103
107
|
* const DB = { a: { knows: ["b","c"] }, b: { knows: ["a","c"] }};
|
|
104
|
-
* defQuery({ cwise: true })(DB, null, "knows", "b")
|
|
105
|
-
* // { a: { knows: ["b","c"] } }
|
|
106
108
|
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
+
* console.log(
|
|
110
|
+
* defQuery({ cwise: true })(DB, null, "knows", "b")
|
|
111
|
+
* );
|
|
112
|
+
* // { a: { knows: ["b", "c"] } }
|
|
113
|
+
*
|
|
114
|
+
* console.log(
|
|
115
|
+
* defQuery({ cwise: false })(DB, null, "knows", (x) => x.includes("b"))
|
|
116
|
+
* );
|
|
117
|
+
* // { a: { knows: ["b", "c"] } }
|
|
109
118
|
* ```
|
|
110
119
|
*
|
|
111
120
|
* @defaultValue true
|
package/match.d.ts
CHANGED
|
@@ -23,30 +23,10 @@ export interface MatchMultipleOpts<T> {
|
|
|
23
23
|
* which contains any of these exclusions is automatically rejected, even if
|
|
24
24
|
* other strings could be matched.
|
|
25
25
|
*
|
|
26
|
-
* See {@link matchMultiple} for more details
|
|
27
|
-
*
|
|
28
|
-
* @param key
|
|
29
|
-
* @param matches
|
|
30
|
-
* @param opts
|
|
31
|
-
* @returns
|
|
32
|
-
*/
|
|
33
|
-
export declare const matchStrings: <T extends QueryObj = QueryObj>(key: QueryTerm["q"][0], matches: string[], opts?: Partial<MatchMultipleOpts<string>>) => QueryTerm<T>;
|
|
34
|
-
/**
|
|
35
|
-
* Returns a {@link QueryTerm} for use with {@link query} to perform set-like
|
|
36
|
-
* intersection or union queries with optional negation/exclusions. Matches set
|
|
37
|
-
* of given values against an item's chosen field of values and by default only
|
|
38
|
-
* succeeds if all provided `includes` can be matched (aka intersection query)
|
|
39
|
-
* and there're no values from `excludes` present.
|
|
40
|
-
*
|
|
41
|
-
* @remarks
|
|
42
|
-
* If the `union` option is true, only one of the provided values needs to
|
|
43
|
-
* match. Exclusions _always_ take precedence.
|
|
44
|
-
*
|
|
45
|
-
* Note: See {@link matchStrings} for a syntax sugar of this function, aimed at
|
|
46
|
-
* matching `string[]` options.
|
|
26
|
+
* See {@link matchMultiple} for more details.
|
|
47
27
|
*
|
|
48
28
|
* @example
|
|
49
|
-
* ```ts
|
|
29
|
+
* ```ts tangle:../export/match-strings.ts
|
|
50
30
|
* import { query, matchStrings } from "@thi.ng/oquery";
|
|
51
31
|
*
|
|
52
32
|
* const DB = [
|
|
@@ -56,22 +36,48 @@ export declare const matchStrings: <T extends QueryObj = QueryObj>(key: QueryTer
|
|
|
56
36
|
* ];
|
|
57
37
|
*
|
|
58
38
|
* // tag intersection
|
|
59
|
-
*
|
|
39
|
+
* console.log(
|
|
40
|
+
* query(DB, [matchStrings("tags", ["a", "b"])])
|
|
41
|
+
* );
|
|
60
42
|
* // [ { id: 1, tags: ["a", "b"] } ]
|
|
61
43
|
*
|
|
62
44
|
* // tag union
|
|
63
|
-
*
|
|
45
|
+
* console.log(
|
|
46
|
+
* query(DB, [matchStrings("tags", ["a", "b"])])
|
|
47
|
+
* );
|
|
64
48
|
* // here returns full DB...
|
|
65
49
|
* // since each item either has `a` and/or `b` tags
|
|
66
50
|
*
|
|
67
51
|
* // tag exclusion (require `a`, disallow `b`)
|
|
68
|
-
*
|
|
52
|
+
* console.log(
|
|
53
|
+
* query(DB, [matchStrings("tags", ["a", "!b"])])
|
|
54
|
+
* );
|
|
69
55
|
* // [ { id: 3, tags: ["c", "a"] } ]
|
|
70
56
|
* ```
|
|
71
57
|
*
|
|
72
58
|
* @param key
|
|
73
59
|
* @param matches
|
|
74
60
|
* @param opts
|
|
61
|
+
* @returns
|
|
62
|
+
*/
|
|
63
|
+
export declare const matchStrings: <T extends QueryObj = QueryObj>(key: QueryTerm["q"][0], matches: string[], opts?: Partial<MatchMultipleOpts<string>>) => QueryTerm<T>;
|
|
64
|
+
/**
|
|
65
|
+
* Returns a {@link QueryTerm} for use with {@link query} to perform set-like
|
|
66
|
+
* intersection or union queries with optional negation/exclusions. Matches set
|
|
67
|
+
* of given values against an item's chosen field of values and by default only
|
|
68
|
+
* succeeds if all provided `includes` can be matched (aka intersection query)
|
|
69
|
+
* and there're no values from `excludes` present.
|
|
70
|
+
*
|
|
71
|
+
* @remarks
|
|
72
|
+
* If the `union` option is true, only one of the provided values needs to
|
|
73
|
+
* match. Exclusions _always_ take precedence.
|
|
74
|
+
*
|
|
75
|
+
* Note: See {@link matchStrings} for a syntax sugar & examples of this
|
|
76
|
+
* function, aimed at matching `string[]` options.
|
|
77
|
+
*
|
|
78
|
+
* @param key
|
|
79
|
+
* @param matches
|
|
80
|
+
* @param opts
|
|
75
81
|
*/
|
|
76
82
|
export declare const matchMultiple: <T extends QueryObj = QueryObj, V = any>(key: QueryTerm["q"][0], includes: V[], excludes: V[], opts?: Partial<MatchMultipleOpts<V>>) => QueryTerm<T>;
|
|
77
83
|
/**
|
|
@@ -89,7 +95,7 @@ export declare const matchMultiple: <T extends QueryObj = QueryObj, V = any>(key
|
|
|
89
95
|
* between operator and value are ignored.
|
|
90
96
|
*
|
|
91
97
|
* @example
|
|
92
|
-
* ```ts
|
|
98
|
+
* ```ts tangle:../export/match-pattern.ts
|
|
93
99
|
* import { query, matchPattern } from "@thi.ng/oquery";
|
|
94
100
|
*
|
|
95
101
|
* const DB = [
|
|
@@ -98,12 +104,19 @@ export declare const matchMultiple: <T extends QueryObj = QueryObj, V = any>(key
|
|
|
98
104
|
* { id: "c", score: 15 },
|
|
99
105
|
* ];
|
|
100
106
|
*
|
|
101
|
-
*
|
|
107
|
+
* console.log(
|
|
108
|
+
* query(DB, [matchPattern("id", /[a-z]{4,}/)])
|
|
109
|
+
* );
|
|
102
110
|
* // [{ id: "bbbb", score: 60 }]
|
|
103
|
-
*
|
|
111
|
+
*
|
|
112
|
+
* console.log(
|
|
113
|
+
* query(DB, [matchPattern("id", ">= c")])
|
|
114
|
+
* );
|
|
104
115
|
* // [{ id: "c", score: 15 }]
|
|
105
116
|
*
|
|
106
|
-
*
|
|
117
|
+
* console.log(
|
|
118
|
+
* query(DB, [matchPattern("score", "<50")])
|
|
119
|
+
* );
|
|
107
120
|
* // [{ id: "a", score: 32 }, { id: "c", score: 15 }]
|
|
108
121
|
* ```
|
|
109
122
|
*
|
package/match.js
CHANGED
|
@@ -19,15 +19,13 @@ const matchMultiple = (key, includes, excludes, opts = {}) => {
|
|
|
19
19
|
(values) => {
|
|
20
20
|
const $values = valueFn ? valueFn(values) : values;
|
|
21
21
|
for (let x of excludes) {
|
|
22
|
-
if ($values.includes(x))
|
|
23
|
-
return false;
|
|
22
|
+
if ($values.includes(x)) return false;
|
|
24
23
|
}
|
|
25
24
|
let match = false;
|
|
26
25
|
for (let x of includes) {
|
|
27
26
|
if ($values.includes(x)) {
|
|
28
27
|
match = true;
|
|
29
|
-
if (union)
|
|
30
|
-
break;
|
|
28
|
+
if (union) break;
|
|
31
29
|
} else if (!union) {
|
|
32
30
|
match = false;
|
|
33
31
|
break;
|
|
@@ -44,8 +42,7 @@ const matchPattern = (key, expr, opts) => {
|
|
|
44
42
|
if (expr instanceof RegExp) {
|
|
45
43
|
re = expr;
|
|
46
44
|
} else {
|
|
47
|
-
if (expr === "*")
|
|
48
|
-
return { q: [key, (x) => x != null], opts };
|
|
45
|
+
if (expr === "*") return { q: [key, (x) => x != null], opts };
|
|
49
46
|
if (/^[<>=!]/.test(expr)) {
|
|
50
47
|
const op = /^[<>=!]+/.exec(expr)[0];
|
|
51
48
|
const arg = expr.substring(op.length).trim();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/oquery",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.42",
|
|
4
4
|
"description": "Datalog-inspired, optimized pattern/predicate query engine for JS objects & arrays of objects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"type": "git",
|
|
11
11
|
"url": "https://github.com/thi-ng/umbrella.git"
|
|
12
12
|
},
|
|
13
|
-
"homepage": "https://
|
|
13
|
+
"homepage": "https://thi.ng/oquery",
|
|
14
14
|
"funding": [
|
|
15
15
|
{
|
|
16
16
|
"type": "github",
|
|
@@ -36,17 +36,17 @@
|
|
|
36
36
|
"tool:tangle": "../../node_modules/.bin/tangle src/**/*.ts"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@thi.ng/api": "^8.11.
|
|
40
|
-
"@thi.ng/checks": "^3.6.
|
|
41
|
-
"@thi.ng/compare": "^2.3.
|
|
42
|
-
"@thi.ng/defmulti": "^3.0.
|
|
43
|
-
"@thi.ng/equiv": "^2.1.
|
|
39
|
+
"@thi.ng/api": "^8.11.3",
|
|
40
|
+
"@thi.ng/checks": "^3.6.5",
|
|
41
|
+
"@thi.ng/compare": "^2.3.6",
|
|
42
|
+
"@thi.ng/defmulti": "^3.0.40",
|
|
43
|
+
"@thi.ng/equiv": "^2.1.59"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@microsoft/api-extractor": "^7.
|
|
47
|
-
"esbuild": "^0.
|
|
48
|
-
"typedoc": "^0.25.
|
|
49
|
-
"typescript": "^5.
|
|
46
|
+
"@microsoft/api-extractor": "^7.47.0",
|
|
47
|
+
"esbuild": "^0.21.5",
|
|
48
|
+
"typedoc": "^0.25.13",
|
|
49
|
+
"typescript": "^5.5.2"
|
|
50
50
|
},
|
|
51
51
|
"keywords": [
|
|
52
52
|
"array",
|
|
@@ -96,5 +96,5 @@
|
|
|
96
96
|
],
|
|
97
97
|
"year": 2020
|
|
98
98
|
},
|
|
99
|
-
"gitHead": "
|
|
99
|
+
"gitHead": "154c95cf9d6bab32174498ec3b5b5d87e42be7f9\n"
|
|
100
100
|
}
|
package/query.js
CHANGED
|
@@ -6,269 +6,268 @@ import { compareByKey } from "@thi.ng/compare/keys";
|
|
|
6
6
|
import { reverse } from "@thi.ng/compare/reverse";
|
|
7
7
|
import { defmulti } from "@thi.ng/defmulti/defmulti";
|
|
8
8
|
import { equiv } from "@thi.ng/equiv";
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const a =
|
|
9
|
+
const __classify = (x) => x != null ? isFunction(x) ? "f" : "l" : "n";
|
|
10
|
+
const __ensureArray = (src) => isArray(src) ? src : [...src];
|
|
11
|
+
const __ensureSet = (src) => isArray(src) ? new Set(src) : src;
|
|
12
|
+
const __intersect = (src) => {
|
|
13
|
+
const a = __ensureArray(src);
|
|
14
14
|
const num = a.length;
|
|
15
15
|
return (b) => {
|
|
16
|
-
const $b =
|
|
16
|
+
const $b = __ensureSet(b);
|
|
17
17
|
for (let i = num; i-- > 0; ) {
|
|
18
|
-
if (!$b.has(a[i]))
|
|
19
|
-
return false;
|
|
18
|
+
if (!$b.has(a[i])) return false;
|
|
20
19
|
}
|
|
21
20
|
return true;
|
|
22
21
|
};
|
|
23
22
|
};
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
const
|
|
23
|
+
const __coerce = (x, isec = false) => isArray(x) ? isec ? __intersect(x) : (y) => x.includes(y) : isSet(x) ? isec ? __intersect(x) : (y) => x.has(y) : x;
|
|
24
|
+
const __coerceStr = (x) => isArray(x) ? __coerce(x.map((y) => String(y))) : isSet(x) ? __coerce(new Set([...x].map((y) => String(y)))) : x == null || isFunction(x) ? x : String(x);
|
|
25
|
+
const __addTriple = (acc, s, p, o) => {
|
|
27
26
|
const sval = acc[s];
|
|
28
27
|
sval ? sval[p] = o : acc[s] = { [p]: o };
|
|
29
28
|
};
|
|
30
|
-
const
|
|
29
|
+
const __match = (o, val, opts) => {
|
|
31
30
|
if (val != null) {
|
|
32
31
|
const pred = isFunction(o) ? o : ($) => opts.equiv(o, $);
|
|
33
32
|
return opts.cwise && isArray(val) ? val.some(pred) : pred(val);
|
|
34
33
|
}
|
|
35
34
|
return false;
|
|
36
35
|
};
|
|
37
|
-
const
|
|
36
|
+
const __collect = (acc, s, p, o, val, opts) => {
|
|
38
37
|
if (val != null) {
|
|
39
38
|
const pred = isFunction(o) ? o : ($) => opts.equiv(o, $);
|
|
40
39
|
if (opts.cwise && isArray(val)) {
|
|
41
40
|
val = val.filter(pred);
|
|
42
|
-
val.length &&
|
|
41
|
+
val.length && __addTriple(acc, s, p, val);
|
|
43
42
|
} else if (pred(val)) {
|
|
44
|
-
|
|
43
|
+
__addTriple(acc, s, p, val);
|
|
45
44
|
}
|
|
46
45
|
}
|
|
47
46
|
};
|
|
48
|
-
const
|
|
49
|
-
const
|
|
47
|
+
const __collectFull = (res, s, val) => res[s] = val;
|
|
48
|
+
const __collectSP = (res, sval, s, p, o, opts) => {
|
|
50
49
|
if (opts.partial) {
|
|
51
50
|
for (let $p in sval) {
|
|
52
|
-
p($p) &&
|
|
51
|
+
p($p) && __collect(res, s, $p, o, sval[$p], opts);
|
|
53
52
|
}
|
|
54
53
|
} else {
|
|
55
54
|
for (let $p in sval) {
|
|
56
|
-
if (p($p) &&
|
|
57
|
-
|
|
55
|
+
if (p($p) && __match(o, sval[$p], opts)) {
|
|
56
|
+
__collectFull(res, s, sval);
|
|
58
57
|
return;
|
|
59
58
|
}
|
|
60
59
|
}
|
|
61
60
|
}
|
|
62
61
|
};
|
|
63
|
-
const
|
|
62
|
+
const __collectSO = (res, sval, s, o, opts) => {
|
|
64
63
|
if (opts.partial) {
|
|
65
64
|
for (let p in sval) {
|
|
66
|
-
|
|
65
|
+
__collect(res, s, p, o, sval[p], opts);
|
|
67
66
|
}
|
|
68
67
|
} else {
|
|
69
68
|
for (let p in sval) {
|
|
70
|
-
if (
|
|
71
|
-
|
|
69
|
+
if (__match(o, sval[p], opts)) {
|
|
70
|
+
__collectFull(res, s, sval);
|
|
72
71
|
return;
|
|
73
72
|
}
|
|
74
73
|
}
|
|
75
74
|
}
|
|
76
75
|
};
|
|
77
|
-
const
|
|
76
|
+
const __queryLL = (res, db, s, p, o, opts) => {
|
|
78
77
|
const sval = db[s];
|
|
79
78
|
const val = sval?.[p];
|
|
80
79
|
if (opts.partial) {
|
|
81
|
-
|
|
80
|
+
__collect(res, s, p, o, val, opts);
|
|
82
81
|
} else {
|
|
83
|
-
|
|
82
|
+
__match(o, val, opts) && __collectFull(res, s, sval);
|
|
84
83
|
}
|
|
85
84
|
};
|
|
86
|
-
const
|
|
85
|
+
const __queryLF = (res, db, s, p, o, opts) => {
|
|
87
86
|
const sval = db[s];
|
|
88
|
-
sval != null &&
|
|
87
|
+
sval != null && __collectSP(res, sval, s, p, o, opts);
|
|
89
88
|
};
|
|
90
|
-
const
|
|
89
|
+
const __queryLN = (res, db, s, _, o, opts) => {
|
|
91
90
|
const sval = db[s];
|
|
92
|
-
sval != null &&
|
|
91
|
+
sval != null && __collectSO(res, sval, s, o, opts);
|
|
93
92
|
};
|
|
94
|
-
const
|
|
93
|
+
const __queryFL = (res, db, s, p, o, opts) => {
|
|
95
94
|
if (opts.partial) {
|
|
96
95
|
for (let $s in db) {
|
|
97
|
-
s($s) &&
|
|
96
|
+
s($s) && __collect(res, $s, p, o, db[$s]?.[p], opts);
|
|
98
97
|
}
|
|
99
98
|
} else {
|
|
100
99
|
for (let $s in db) {
|
|
101
100
|
const sval = db[$s];
|
|
102
|
-
s($s) &&
|
|
101
|
+
s($s) && __match(o, sval?.[p], opts) && __collectFull(res, $s, sval);
|
|
103
102
|
}
|
|
104
103
|
}
|
|
105
104
|
};
|
|
106
|
-
const
|
|
105
|
+
const __queryFF = (res, db, s, p, o, opts) => {
|
|
107
106
|
for (let $s in db) {
|
|
108
|
-
s($s) &&
|
|
107
|
+
s($s) && __collectSP(res, db[$s], $s, p, o, opts);
|
|
109
108
|
}
|
|
110
109
|
};
|
|
111
|
-
const
|
|
110
|
+
const __queryFFNPartial = (res, db, s, p) => {
|
|
112
111
|
for (let $s in db) {
|
|
113
|
-
s($s)
|
|
112
|
+
if (s($s)) {
|
|
113
|
+
const sval = db[$s];
|
|
114
|
+
for (let $p in sval) {
|
|
115
|
+
p($p) && __addTriple(res, $s, $p, sval[$p]);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
const __queryFFN = (res, db, s, p) => {
|
|
121
|
+
for (let $s in db) {
|
|
122
|
+
if (s($s)) {
|
|
123
|
+
const sval = db[$s];
|
|
124
|
+
for (let $p in sval) {
|
|
125
|
+
if (p($p)) {
|
|
126
|
+
__collectFull(res, $s, sval);
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
const __queryFN = (res, db, s, _, o, opts) => {
|
|
134
|
+
for (let $s in db) {
|
|
135
|
+
s($s) && __collectSO(res, db[$s], $s, o, opts);
|
|
114
136
|
}
|
|
115
137
|
};
|
|
116
|
-
const
|
|
138
|
+
const __queryNL = (res, db, _, p, o, opts) => {
|
|
117
139
|
if (opts.partial) {
|
|
118
140
|
for (let s in db) {
|
|
119
|
-
|
|
141
|
+
__collect(res, s, p, o, db[s][p], opts);
|
|
120
142
|
}
|
|
121
143
|
} else {
|
|
122
144
|
for (let s in db) {
|
|
123
145
|
const sval = db[s];
|
|
124
|
-
|
|
146
|
+
__match(o, sval[p], opts) && __collectFull(res, s, sval);
|
|
125
147
|
}
|
|
126
148
|
}
|
|
127
149
|
};
|
|
128
|
-
const
|
|
150
|
+
const __queryNF = (res, db, _, p, o, opts) => {
|
|
151
|
+
for (let s in db) {
|
|
152
|
+
__collectSP(res, db[s], s, p, o, opts);
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
const __queryNN = (res, db, _, __, o, opts) => {
|
|
129
156
|
for (let s in db) {
|
|
130
|
-
|
|
157
|
+
__collectSO(res, db[s], s, o, opts);
|
|
131
158
|
}
|
|
132
159
|
};
|
|
133
|
-
const
|
|
160
|
+
const __queryNLNPartial = (res, db, _, p) => {
|
|
134
161
|
for (let s in db) {
|
|
135
|
-
|
|
162
|
+
const val = db[s][p];
|
|
163
|
+
val != null && __addTriple(res, s, p, val);
|
|
136
164
|
}
|
|
137
165
|
};
|
|
138
|
-
const
|
|
166
|
+
const __queryNLN = (res, db, _, p) => {
|
|
167
|
+
for (let s in db) {
|
|
168
|
+
const sval = db[s];
|
|
169
|
+
const val = sval[p];
|
|
170
|
+
val != null && __collectFull(res, s, sval);
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
const __querySP = (res, sval, s, p, _, opts) => {
|
|
139
174
|
if (opts.partial) {
|
|
140
175
|
for (let q in sval) {
|
|
141
176
|
if (p(q)) {
|
|
142
177
|
const val = sval[q];
|
|
143
|
-
val != null &&
|
|
178
|
+
val != null && __addTriple(res, s, q, val);
|
|
144
179
|
}
|
|
145
180
|
}
|
|
146
181
|
} else {
|
|
147
182
|
for (let q in sval) {
|
|
148
183
|
if (p(q)) {
|
|
149
|
-
|
|
184
|
+
__collectFull(res, s, sval);
|
|
150
185
|
return;
|
|
151
186
|
}
|
|
152
187
|
}
|
|
153
188
|
}
|
|
154
189
|
};
|
|
155
|
-
const
|
|
190
|
+
const __queryO = (res, db, s, p, _, opts) => {
|
|
156
191
|
const sval = db[s];
|
|
157
192
|
const val = sval?.[p];
|
|
158
|
-
val != null && (opts.partial ?
|
|
193
|
+
val != null && (opts.partial ? __addTriple(res, s, p, val) : __collectFull(res, s, sval));
|
|
159
194
|
};
|
|
160
195
|
const IMPLS = {
|
|
161
|
-
lll:
|
|
162
|
-
llf:
|
|
163
|
-
lln:
|
|
164
|
-
lfl:
|
|
165
|
-
lff:
|
|
196
|
+
lll: __queryLL,
|
|
197
|
+
llf: __queryLL,
|
|
198
|
+
lln: __queryO,
|
|
199
|
+
lfl: __queryLF,
|
|
200
|
+
lff: __queryLF,
|
|
166
201
|
lfn: (res, db, s, p, _, opts) => {
|
|
167
202
|
const sval = db[s];
|
|
168
|
-
sval != null &&
|
|
203
|
+
sval != null && __querySP(res, sval, s, p, null, opts);
|
|
169
204
|
},
|
|
170
|
-
lnl:
|
|
171
|
-
lnf:
|
|
205
|
+
lnl: __queryLN,
|
|
206
|
+
lnf: __queryLN,
|
|
172
207
|
lnn: (res, db, s) => {
|
|
173
208
|
const sval = db[s];
|
|
174
|
-
sval != null &&
|
|
209
|
+
sval != null && __collectFull(res, s, sval);
|
|
175
210
|
},
|
|
176
|
-
fll:
|
|
177
|
-
flf:
|
|
211
|
+
fll: __queryFL,
|
|
212
|
+
flf: __queryFL,
|
|
178
213
|
fln: (res, db, s, p, _, opts) => {
|
|
179
214
|
for (let $s in db) {
|
|
180
|
-
s($s) &&
|
|
181
|
-
}
|
|
182
|
-
},
|
|
183
|
-
ffl: queryFF,
|
|
184
|
-
fff: queryFF,
|
|
185
|
-
ffn: (res, db, s, p, _, opts) => {
|
|
186
|
-
if (opts.partial) {
|
|
187
|
-
for (let $s in db) {
|
|
188
|
-
if (s($s)) {
|
|
189
|
-
const sval = db[$s];
|
|
190
|
-
for (let $p in sval) {
|
|
191
|
-
p($p) && addTriple(res, $s, $p, sval[$p]);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
} else {
|
|
196
|
-
for (let $s in db) {
|
|
197
|
-
if (s($s)) {
|
|
198
|
-
const sval = db[$s];
|
|
199
|
-
for (let $p in sval) {
|
|
200
|
-
if (p($p)) {
|
|
201
|
-
collectFull(res, $s, sval);
|
|
202
|
-
break;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
}
|
|
215
|
+
s($s) && __queryO(res, db, $s, p, null, opts);
|
|
207
216
|
}
|
|
208
217
|
},
|
|
209
|
-
|
|
210
|
-
|
|
218
|
+
ffl: __queryFF,
|
|
219
|
+
fff: __queryFF,
|
|
220
|
+
ffn: (res, db, s, p, o, opts) => (opts.partial ? __queryFFNPartial : __queryFFN)(res, db, s, p, o, opts),
|
|
221
|
+
fnl: __queryFN,
|
|
222
|
+
fnf: __queryFN,
|
|
211
223
|
fnn: (res, db, s) => {
|
|
212
224
|
for (let $s in db) {
|
|
213
225
|
if (s($s)) {
|
|
214
226
|
const sval = db[$s];
|
|
215
|
-
sval != null &&
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
},
|
|
219
|
-
nll: queryNL,
|
|
220
|
-
nlf: queryNL,
|
|
221
|
-
nln: (res, db, _, p, __, opts) => {
|
|
222
|
-
if (opts.partial) {
|
|
223
|
-
for (let s in db) {
|
|
224
|
-
const val = db[s][p];
|
|
225
|
-
val != null && addTriple(res, s, p, val);
|
|
226
|
-
}
|
|
227
|
-
} else {
|
|
228
|
-
for (let s in db) {
|
|
229
|
-
const sval = db[s];
|
|
230
|
-
const val = sval[p];
|
|
231
|
-
val != null && collectFull(res, s, sval);
|
|
227
|
+
sval != null && __collectFull(res, $s, sval);
|
|
232
228
|
}
|
|
233
229
|
}
|
|
234
230
|
},
|
|
235
|
-
|
|
236
|
-
|
|
231
|
+
nll: __queryNL,
|
|
232
|
+
nlf: __queryNL,
|
|
233
|
+
nln: (res, db, s, p, o, opts) => (opts.partial ? __queryNLNPartial : __queryNLN)(res, db, s, p, o, opts),
|
|
234
|
+
nfl: __queryNF,
|
|
235
|
+
nff: __queryNF,
|
|
237
236
|
nfn: (res, db, _, p, __, opts) => {
|
|
238
237
|
for (let s in db) {
|
|
239
|
-
|
|
238
|
+
__querySP(res, db[s], s, p, null, opts);
|
|
240
239
|
}
|
|
241
240
|
},
|
|
242
|
-
nnl:
|
|
243
|
-
nnf:
|
|
241
|
+
nnl: __queryNN,
|
|
242
|
+
nnf: __queryNN,
|
|
244
243
|
nnn: (res, db) => Object.assign(res, db)
|
|
245
244
|
};
|
|
246
|
-
const
|
|
247
|
-
const
|
|
245
|
+
const __impl = defmulti((_, __, s, p, o) => __classify(s) + __classify(p) + __classify(o), {}, IMPLS);
|
|
246
|
+
const __objQuery = (src, opts, args) => {
|
|
248
247
|
const isIsec = opts.cwise && opts.intersect;
|
|
249
248
|
isIsec && (opts.cwise = false);
|
|
250
249
|
let [s, p, o, out] = args;
|
|
251
250
|
out = out || {};
|
|
252
|
-
|
|
251
|
+
__impl(
|
|
253
252
|
out,
|
|
254
253
|
src,
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
254
|
+
__coerceStr(s),
|
|
255
|
+
__coerceStr(p),
|
|
256
|
+
__coerce(o, isIsec),
|
|
258
257
|
opts
|
|
259
258
|
);
|
|
260
259
|
return out;
|
|
261
260
|
};
|
|
262
|
-
const
|
|
261
|
+
const __arrayQuery = (src, opts, p, o, collect) => {
|
|
263
262
|
const isIsec = opts.cwise && opts.intersect;
|
|
264
263
|
isIsec && (opts.cwise = false);
|
|
265
|
-
const $p =
|
|
266
|
-
const $o =
|
|
267
|
-
const
|
|
264
|
+
const $p = __coerceStr(p);
|
|
265
|
+
const $o = __coerce(o, isIsec);
|
|
266
|
+
const impl = IMPLS["n" + __classify($p) + __classify($o)];
|
|
268
267
|
for (let i = 0, n = src.length; i < n; i++) {
|
|
269
268
|
const res = {};
|
|
270
|
-
|
|
271
|
-
res._ &&
|
|
269
|
+
impl(res, { _: src[i] }, "_", $p, $o, opts);
|
|
270
|
+
res._ && collect(res._, i);
|
|
272
271
|
}
|
|
273
272
|
};
|
|
274
273
|
const DEFAULT_OPTS = {
|
|
@@ -282,10 +281,10 @@ const defQuery = (opts) => {
|
|
|
282
281
|
return (src, ...args) => {
|
|
283
282
|
if (isArray(src)) {
|
|
284
283
|
const out = args[2] || [];
|
|
285
|
-
|
|
284
|
+
__arrayQuery(src, $opts, args[0], args[1], (x) => out.push(x));
|
|
286
285
|
return out;
|
|
287
286
|
} else {
|
|
288
|
-
return
|
|
287
|
+
return __objQuery(src, $opts, args);
|
|
289
288
|
}
|
|
290
289
|
};
|
|
291
290
|
};
|
|
@@ -294,31 +293,27 @@ const defKeyQuery = (opts) => {
|
|
|
294
293
|
return (src, ...args) => {
|
|
295
294
|
if (isArray(src)) {
|
|
296
295
|
const out = args[2] || /* @__PURE__ */ new Set();
|
|
297
|
-
|
|
296
|
+
__arrayQuery(src, $opts, args[0], args[1], (_, i) => out.add(i));
|
|
298
297
|
return out;
|
|
299
298
|
} else {
|
|
300
|
-
const res =
|
|
299
|
+
const res = __objQuery(src, $opts, args.slice(0, 3));
|
|
301
300
|
const out = args[3];
|
|
302
|
-
if (!out)
|
|
303
|
-
|
|
304
|
-
for (let k in res)
|
|
305
|
-
out.add(k);
|
|
301
|
+
if (!out) return new Set(Object.keys(res));
|
|
302
|
+
for (let k in res) out.add(k);
|
|
306
303
|
return out;
|
|
307
304
|
}
|
|
308
305
|
};
|
|
309
306
|
};
|
|
310
307
|
const query = (db, terms, opts = {}) => {
|
|
311
308
|
for (let term of terms) {
|
|
312
|
-
if (!term)
|
|
313
|
-
continue;
|
|
309
|
+
if (!term) continue;
|
|
314
310
|
db = defQuery(term.opts)(
|
|
315
311
|
db,
|
|
316
312
|
term.q[0],
|
|
317
313
|
term.q[1]
|
|
318
314
|
);
|
|
319
315
|
term.post && (db = term.post(db));
|
|
320
|
-
if (!db.length)
|
|
321
|
-
return db;
|
|
316
|
+
if (!db.length) return db;
|
|
322
317
|
}
|
|
323
318
|
const limit = opts.limit || 0;
|
|
324
319
|
if (limit > 0 && limit < db.length) {
|