ochre-sdk 0.21.5 → 0.21.7
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/dist/index.d.mts +10 -4
- package/dist/index.mjs +282 -315
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -677,7 +677,7 @@ type QueryLeaf = {
|
|
|
677
677
|
target: "property";
|
|
678
678
|
propertyVariable?: string;
|
|
679
679
|
dataType: Exclude<Exclude<PropertyValueContentType, "coordinate">, "date" | "dateTime">;
|
|
680
|
-
|
|
680
|
+
value?: string;
|
|
681
681
|
from?: never;
|
|
682
682
|
to?: never;
|
|
683
683
|
matchMode: "includes" | "exact";
|
|
@@ -688,7 +688,6 @@ type QueryLeaf = {
|
|
|
688
688
|
target: "property";
|
|
689
689
|
propertyVariable: string;
|
|
690
690
|
dataType: "date" | "dateTime";
|
|
691
|
-
propertyValues?: never;
|
|
692
691
|
value: string;
|
|
693
692
|
from?: never;
|
|
694
693
|
to?: never;
|
|
@@ -700,7 +699,6 @@ type QueryLeaf = {
|
|
|
700
699
|
target: "property";
|
|
701
700
|
propertyVariable: string;
|
|
702
701
|
dataType: "date" | "dateTime";
|
|
703
|
-
propertyValues?: never;
|
|
704
702
|
value?: never;
|
|
705
703
|
from: string;
|
|
706
704
|
to?: string;
|
|
@@ -712,7 +710,6 @@ type QueryLeaf = {
|
|
|
712
710
|
target: "property";
|
|
713
711
|
propertyVariable: string;
|
|
714
712
|
dataType: "date" | "dateTime";
|
|
715
|
-
propertyValues?: never;
|
|
716
713
|
value?: never;
|
|
717
714
|
from?: string;
|
|
718
715
|
to: string;
|
|
@@ -720,6 +717,15 @@ type QueryLeaf = {
|
|
|
720
717
|
isCaseSensitive: boolean;
|
|
721
718
|
language: string;
|
|
722
719
|
isNegated?: boolean;
|
|
720
|
+
} | {
|
|
721
|
+
target: "property";
|
|
722
|
+
propertyVariable?: string;
|
|
723
|
+
dataType: "all";
|
|
724
|
+
value: string;
|
|
725
|
+
matchMode: "includes" | "exact";
|
|
726
|
+
isCaseSensitive: boolean;
|
|
727
|
+
language: string;
|
|
728
|
+
isNegated?: boolean;
|
|
723
729
|
} | {
|
|
724
730
|
target: "string";
|
|
725
731
|
value: string;
|
package/dist/index.mjs
CHANGED
|
@@ -768,15 +768,15 @@ const setQueryLeafSchema = z.union([
|
|
|
768
768
|
"time",
|
|
769
769
|
"IDREF"
|
|
770
770
|
]),
|
|
771
|
-
|
|
771
|
+
value: z.string().optional(),
|
|
772
772
|
matchMode: z.enum(["includes", "exact"]),
|
|
773
773
|
isCaseSensitive: z.boolean(),
|
|
774
774
|
language: z.string().default("eng"),
|
|
775
775
|
isNegated: z.boolean().optional().default(false)
|
|
776
776
|
}).strict().superRefine((value, ctx) => {
|
|
777
|
-
if (value.propertyVariable == null && value.
|
|
777
|
+
if (value.propertyVariable == null && value.value == null) ctx.addIssue({
|
|
778
778
|
code: "custom",
|
|
779
|
-
message: "Property queries must include at least one propertyVariable or
|
|
779
|
+
message: "Property queries must include at least one propertyVariable or value"
|
|
780
780
|
});
|
|
781
781
|
}),
|
|
782
782
|
z.object({
|
|
@@ -815,6 +815,16 @@ const setQueryLeafSchema = z.union([
|
|
|
815
815
|
language: z.string().default("eng"),
|
|
816
816
|
isNegated: z.boolean().optional().default(false)
|
|
817
817
|
}).strict(),
|
|
818
|
+
z.object({
|
|
819
|
+
target: z.literal("property"),
|
|
820
|
+
propertyVariable: uuidSchema.optional(),
|
|
821
|
+
dataType: z.literal("all"),
|
|
822
|
+
value: z.string(),
|
|
823
|
+
matchMode: z.enum(["includes", "exact"]),
|
|
824
|
+
isCaseSensitive: z.boolean(),
|
|
825
|
+
language: z.string().default("eng"),
|
|
826
|
+
isNegated: z.boolean().optional().default(false)
|
|
827
|
+
}).strict(),
|
|
818
828
|
z.object({
|
|
819
829
|
target: z.literal("string"),
|
|
820
830
|
value: z.string(),
|
|
@@ -2172,10 +2182,6 @@ function buildFlattenedContentValuesExpression(contentNodesExpression) {
|
|
|
2172
2182
|
return `for $content in ${contentNodesExpression}
|
|
2173
2183
|
return string-join($content//text(), "")`;
|
|
2174
2184
|
}
|
|
2175
|
-
function buildNodeStringValuesExpression(nodesExpression) {
|
|
2176
|
-
return `for $node in ${nodesExpression}
|
|
2177
|
-
return string($node)`;
|
|
2178
|
-
}
|
|
2179
2185
|
function buildSearchableContentNodesExpression(contentNodesExpression) {
|
|
2180
2186
|
return `for $content in ${contentNodesExpression}
|
|
2181
2187
|
return (
|
|
@@ -2190,17 +2196,46 @@ function buildCombinedSearchableContentNodesExpression(contentNodesExpressions)
|
|
|
2190
2196
|
if (searchableExpressions.length === 1) return searchableExpressions[0] ?? "()";
|
|
2191
2197
|
return `(${searchableExpressions.join(", ")})`;
|
|
2192
2198
|
}
|
|
2193
|
-
function
|
|
2194
|
-
const
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2199
|
+
function buildPropertyValueNodesExpression(params) {
|
|
2200
|
+
const predicates = [];
|
|
2201
|
+
if (params?.excludeInherited) predicates.push(`not(@inherited="true")`);
|
|
2202
|
+
for (const excludedDataType of params?.excludedDataTypes ?? []) predicates.push(`not(@dataType=${stringLiteral(excludedDataType)})`);
|
|
2203
|
+
if (predicates.length === 0) return "value";
|
|
2204
|
+
return `value[${predicates.join(" and ")}]`;
|
|
2205
|
+
}
|
|
2206
|
+
function buildPropertyValueContentNodesExpression(params) {
|
|
2207
|
+
const { language, excludeInherited, excludedDataTypes } = params;
|
|
2208
|
+
return `${buildPropertyValueNodesExpression({
|
|
2209
|
+
excludeInherited,
|
|
2210
|
+
excludedDataTypes
|
|
2211
|
+
})}/content[@xml:lang="${language}"]`;
|
|
2212
|
+
}
|
|
2213
|
+
function buildPropertyValueContentValuesExpression(params) {
|
|
2214
|
+
return buildFlattenedContentValuesExpression(buildPropertyValueContentNodesExpression(params));
|
|
2215
|
+
}
|
|
2216
|
+
function buildPropertyValueRawValuesExpression(params) {
|
|
2217
|
+
return `for $value in ${buildPropertyValueNodesExpression(params)}[@rawValue]
|
|
2218
|
+
return string($value/@rawValue)`;
|
|
2219
|
+
}
|
|
2220
|
+
function buildPropertyValueDirectTextValuesExpression(params) {
|
|
2221
|
+
return `for $value in ${buildPropertyValueNodesExpression(params)}
|
|
2222
|
+
let $candidate := string-join($value/text(), "")
|
|
2223
|
+
where normalize-space($candidate) != ""
|
|
2224
|
+
return $candidate`;
|
|
2225
|
+
}
|
|
2226
|
+
function buildPropertyScalarValueExpressions() {
|
|
2227
|
+
return [buildPropertyValueRawValuesExpression(), buildPropertyValueDirectTextValuesExpression()];
|
|
2228
|
+
}
|
|
2229
|
+
function buildAllPropertyValueExpressions(language) {
|
|
2230
|
+
const params = { excludedDataTypes: ["IDREF"] };
|
|
2231
|
+
return [
|
|
2232
|
+
buildPropertyValueRawValuesExpression(params),
|
|
2233
|
+
buildPropertyValueContentValuesExpression({
|
|
2234
|
+
language,
|
|
2235
|
+
...params
|
|
2236
|
+
}),
|
|
2237
|
+
buildPropertyValueDirectTextValuesExpression(params)
|
|
2238
|
+
];
|
|
2204
2239
|
}
|
|
2205
2240
|
/**
|
|
2206
2241
|
* Build a string match predicate for an XQuery string.
|
|
@@ -2210,10 +2245,16 @@ function buildRawStringMatchPredicate(params) {
|
|
|
2210
2245
|
const comparedValueLiteral = stringLiteral(isCaseSensitive ? value : value.toLowerCase());
|
|
2211
2246
|
const candidateVar = "$candidate";
|
|
2212
2247
|
const comparedCandidate = isCaseSensitive ? candidateVar : `lower-case(${candidateVar})`;
|
|
2213
|
-
if (matchMode === "includes") return `
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2248
|
+
if (matchMode === "includes") return `exists(
|
|
2249
|
+
for ${candidateVar} in (${valueExpression})
|
|
2250
|
+
where contains(${comparedCandidate}, ${comparedValueLiteral})
|
|
2251
|
+
return ${candidateVar}
|
|
2252
|
+
)`;
|
|
2253
|
+
return `exists(
|
|
2254
|
+
for ${candidateVar} in (${valueExpression})
|
|
2255
|
+
where ${comparedCandidate} = ${comparedValueLiteral}
|
|
2256
|
+
return ${candidateVar}
|
|
2257
|
+
)`;
|
|
2217
2258
|
}
|
|
2218
2259
|
/**
|
|
2219
2260
|
* Build a combined raw string match predicate for multiple paths.
|
|
@@ -2221,30 +2262,53 @@ function buildRawStringMatchPredicate(params) {
|
|
|
2221
2262
|
function buildCombinedRawStringMatchPredicate(params) {
|
|
2222
2263
|
const { valueExpressions, value, matchMode, isCaseSensitive } = params;
|
|
2223
2264
|
const predicates = [];
|
|
2224
|
-
for (const valueExpression of valueExpressions) predicates.push(buildRawStringMatchPredicate({
|
|
2265
|
+
for (const valueExpression of valueExpressions) predicates.push(`(${buildRawStringMatchPredicate({
|
|
2225
2266
|
valueExpression,
|
|
2226
2267
|
value,
|
|
2227
2268
|
matchMode,
|
|
2228
2269
|
isCaseSensitive
|
|
2229
|
-
}));
|
|
2270
|
+
})})`);
|
|
2230
2271
|
return buildOrPredicate(predicates);
|
|
2231
2272
|
}
|
|
2232
2273
|
/**
|
|
2233
2274
|
* Build CTS word-query options for API v2 includes search.
|
|
2234
2275
|
*/
|
|
2235
|
-
function buildCtsQueryOptionsExpression(
|
|
2236
|
-
|
|
2276
|
+
function buildCtsQueryOptionsExpression(params) {
|
|
2277
|
+
const { isCaseSensitive, isWildcarded } = params;
|
|
2278
|
+
const options = [
|
|
2237
2279
|
isCaseSensitive ? "case-sensitive" : "case-insensitive",
|
|
2238
2280
|
"diacritic-insensitive",
|
|
2239
2281
|
"punctuation-insensitive"
|
|
2240
|
-
]
|
|
2282
|
+
];
|
|
2283
|
+
if (isWildcarded) options.push("wildcarded");
|
|
2284
|
+
return `(${options.map((option) => stringLiteral(option)).join(", ")})`;
|
|
2285
|
+
}
|
|
2286
|
+
function buildWildcardedTermExpression(termExpression) {
|
|
2287
|
+
return `fn:concat("*", ${termExpression}, "*")`;
|
|
2241
2288
|
}
|
|
2242
2289
|
/**
|
|
2243
2290
|
* Build a CTS word-query expression for an XQuery term.
|
|
2244
2291
|
*/
|
|
2245
2292
|
function buildCtsWordQueryExpression(params) {
|
|
2246
|
-
const { termExpression, isCaseSensitive } = params;
|
|
2247
|
-
return `cts:word-query(${termExpression}, ${buildCtsQueryOptionsExpression(
|
|
2293
|
+
const { termExpression, isCaseSensitive, isWildcarded } = params;
|
|
2294
|
+
return `cts:word-query(${isWildcarded ? buildWildcardedTermExpression(termExpression) : termExpression}, ${buildCtsQueryOptionsExpression({
|
|
2295
|
+
isCaseSensitive,
|
|
2296
|
+
isWildcarded
|
|
2297
|
+
})})`;
|
|
2298
|
+
}
|
|
2299
|
+
function buildCtsElementWordQueryExpression(params) {
|
|
2300
|
+
const { elementName, termExpression, isCaseSensitive, isWildcarded } = params;
|
|
2301
|
+
return `cts:element-word-query(xs:QName("${elementName}"), ${isWildcarded ? buildWildcardedTermExpression(termExpression) : termExpression}, ${buildCtsQueryOptionsExpression({
|
|
2302
|
+
isCaseSensitive,
|
|
2303
|
+
isWildcarded
|
|
2304
|
+
})})`;
|
|
2305
|
+
}
|
|
2306
|
+
function buildCtsElementAttributeWordQueryExpression(params) {
|
|
2307
|
+
const { elementName, attributeName, termExpression, isCaseSensitive, isWildcarded } = params;
|
|
2308
|
+
return `cts:element-attribute-word-query(xs:QName("${elementName}"), xs:QName("${attributeName}"), ${isWildcarded ? buildWildcardedTermExpression(termExpression) : termExpression}, ${buildCtsQueryOptionsExpression({
|
|
2309
|
+
isCaseSensitive,
|
|
2310
|
+
isWildcarded
|
|
2311
|
+
})})`;
|
|
2248
2312
|
}
|
|
2249
2313
|
/**
|
|
2250
2314
|
* Build tokenized search declarations for CTS-backed queries.
|
|
@@ -2268,8 +2332,8 @@ function buildTokenizedSearchDeclarations(params) {
|
|
|
2268
2332
|
termsVar
|
|
2269
2333
|
};
|
|
2270
2334
|
}
|
|
2271
|
-
function
|
|
2272
|
-
const {
|
|
2335
|
+
function buildCtsCandidateQuery(params) {
|
|
2336
|
+
const { value, isCaseSensitive, queryKey, buildCandidateTermQuery } = params;
|
|
2273
2337
|
const tokenizedSearchDeclarations = buildTokenizedSearchDeclarations({
|
|
2274
2338
|
value,
|
|
2275
2339
|
isCaseSensitive,
|
|
@@ -2277,18 +2341,12 @@ function buildCtsIncludesPredicate(params) {
|
|
|
2277
2341
|
});
|
|
2278
2342
|
const termQueriesVar = `$query${queryKey}TermQueries`;
|
|
2279
2343
|
const candidateQueryVar = `$query${queryKey}CandidateQuery`;
|
|
2280
|
-
const fallbackPredicate = buildRawStringMatchPredicate({
|
|
2281
|
-
valueExpression: fallbackValueExpression,
|
|
2282
|
-
value,
|
|
2283
|
-
matchMode: "includes",
|
|
2284
|
-
isCaseSensitive
|
|
2285
|
-
});
|
|
2286
2344
|
if (tokenizeIncludesSearchValue({
|
|
2287
2345
|
value,
|
|
2288
2346
|
isCaseSensitive
|
|
2289
2347
|
}).length === 0) return {
|
|
2290
2348
|
declarations: [],
|
|
2291
|
-
|
|
2349
|
+
termsVar: tokenizedSearchDeclarations.termsVar,
|
|
2292
2350
|
candidateQueryVar: null
|
|
2293
2351
|
};
|
|
2294
2352
|
return {
|
|
@@ -2304,14 +2362,43 @@ function buildCtsIncludesPredicate(params) {
|
|
|
2304
2362
|
then cts:and-query(${termQueriesVar})
|
|
2305
2363
|
else ()`
|
|
2306
2364
|
],
|
|
2307
|
-
|
|
2308
|
-
searchableNodesExpression,
|
|
2309
|
-
termsExpression: tokenizedSearchDeclarations.termsVar,
|
|
2310
|
-
isCaseSensitive
|
|
2311
|
-
}),
|
|
2365
|
+
termsVar: tokenizedSearchDeclarations.termsVar,
|
|
2312
2366
|
candidateQueryVar
|
|
2313
2367
|
};
|
|
2314
2368
|
}
|
|
2369
|
+
function buildCtsIncludesPredicate(params) {
|
|
2370
|
+
const { searchableNodesExpression, fallbackValueExpression, value, isCaseSensitive, queryKey, buildCandidateTermQuery } = params;
|
|
2371
|
+
const candidateQuery = buildCtsCandidateQuery({
|
|
2372
|
+
value,
|
|
2373
|
+
isCaseSensitive,
|
|
2374
|
+
queryKey,
|
|
2375
|
+
buildCandidateTermQuery
|
|
2376
|
+
});
|
|
2377
|
+
const fallbackPredicate = buildRawStringMatchPredicate({
|
|
2378
|
+
valueExpression: fallbackValueExpression,
|
|
2379
|
+
value,
|
|
2380
|
+
matchMode: "includes",
|
|
2381
|
+
isCaseSensitive
|
|
2382
|
+
});
|
|
2383
|
+
if (candidateQuery.candidateQueryVar == null) return {
|
|
2384
|
+
declarations: [],
|
|
2385
|
+
predicate: fallbackPredicate,
|
|
2386
|
+
candidateQueryVar: null
|
|
2387
|
+
};
|
|
2388
|
+
return {
|
|
2389
|
+
declarations: candidateQuery.declarations,
|
|
2390
|
+
predicate: `(every $term in ${candidateQuery.termsVar}
|
|
2391
|
+
satisfies some $searchNode in (${searchableNodesExpression})
|
|
2392
|
+
satisfies cts:contains(
|
|
2393
|
+
$searchNode,
|
|
2394
|
+
${buildCtsWordQueryExpression({
|
|
2395
|
+
termExpression: "$term",
|
|
2396
|
+
isCaseSensitive
|
|
2397
|
+
})}
|
|
2398
|
+
))`,
|
|
2399
|
+
candidateQueryVar: candidateQuery.candidateQueryVar
|
|
2400
|
+
};
|
|
2401
|
+
}
|
|
2315
2402
|
/**
|
|
2316
2403
|
* Build the raw search paths for item-level string search.
|
|
2317
2404
|
*/
|
|
@@ -2364,14 +2451,14 @@ function buildItemStringPropertyValueBranch(params) {
|
|
|
2364
2451
|
* Build an item-level CTS string search predicate.
|
|
2365
2452
|
*/
|
|
2366
2453
|
function buildItemStringSearchClause(params) {
|
|
2367
|
-
const { query, version, queryKey } = params;
|
|
2454
|
+
const { query, version, queryKey, allowCtsPredicates } = params;
|
|
2368
2455
|
const fallbackPredicate = buildCombinedRawStringMatchPredicate({
|
|
2369
2456
|
valueExpressions: buildItemStringSearchPaths(query.language),
|
|
2370
2457
|
value: query.value,
|
|
2371
2458
|
matchMode: query.matchMode,
|
|
2372
2459
|
isCaseSensitive: query.isCaseSensitive
|
|
2373
2460
|
});
|
|
2374
|
-
if (query.matchMode !== "includes" || version !== 2) return {
|
|
2461
|
+
if (!allowCtsPredicates || query.matchMode !== "includes" || version !== 2) return {
|
|
2375
2462
|
declarations: [],
|
|
2376
2463
|
predicate: fallbackPredicate,
|
|
2377
2464
|
candidateQueryVar: null
|
|
@@ -2468,75 +2555,28 @@ function buildPropertyStringCandidateBranch(params) {
|
|
|
2468
2555
|
)
|
|
2469
2556
|
)`;
|
|
2470
2557
|
}
|
|
2471
|
-
function
|
|
2558
|
+
function buildPropertyScalarCandidateBranch(params) {
|
|
2472
2559
|
const { termExpression, isCaseSensitive } = params;
|
|
2473
2560
|
return `cts:element-query(xs:QName("properties"),
|
|
2474
2561
|
cts:element-query(xs:QName("property"),
|
|
2475
|
-
cts:
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
${termExpression},
|
|
2491
|
-
${buildCtsQueryOptionsExpression(isCaseSensitive)}
|
|
2492
|
-
)
|
|
2562
|
+
cts:or-query((
|
|
2563
|
+
${buildCtsElementAttributeWordQueryExpression({
|
|
2564
|
+
elementName: "value",
|
|
2565
|
+
attributeName: "rawValue",
|
|
2566
|
+
termExpression,
|
|
2567
|
+
isCaseSensitive,
|
|
2568
|
+
isWildcarded: true
|
|
2569
|
+
})},
|
|
2570
|
+
${buildCtsElementWordQueryExpression({
|
|
2571
|
+
elementName: "value",
|
|
2572
|
+
termExpression,
|
|
2573
|
+
isCaseSensitive,
|
|
2574
|
+
isWildcarded: true
|
|
2575
|
+
})}
|
|
2576
|
+
))
|
|
2493
2577
|
)
|
|
2494
2578
|
)`;
|
|
2495
2579
|
}
|
|
2496
|
-
function buildPropertySimpleValueRawValueExpression() {
|
|
2497
|
-
return buildNodeStringValuesExpression("value/@rawValue");
|
|
2498
|
-
}
|
|
2499
|
-
function buildPropertySimpleValueTextExpression() {
|
|
2500
|
-
return buildNodeStringValuesExpression("value[not(*)]/text()");
|
|
2501
|
-
}
|
|
2502
|
-
function buildPropertySimpleValueSearchableNodesExpression() {
|
|
2503
|
-
return "value[not(*)]";
|
|
2504
|
-
}
|
|
2505
|
-
function buildPropertyRawValueOrTextRawPredicate(params) {
|
|
2506
|
-
const { value, matchMode, isCaseSensitive } = params;
|
|
2507
|
-
return buildOrPredicate([buildRawStringMatchPredicate({
|
|
2508
|
-
valueExpression: buildPropertySimpleValueRawValueExpression(),
|
|
2509
|
-
value,
|
|
2510
|
-
matchMode,
|
|
2511
|
-
isCaseSensitive
|
|
2512
|
-
}), buildRawStringMatchPredicate({
|
|
2513
|
-
valueExpression: buildPropertySimpleValueTextExpression(),
|
|
2514
|
-
value,
|
|
2515
|
-
matchMode,
|
|
2516
|
-
isCaseSensitive
|
|
2517
|
-
})]);
|
|
2518
|
-
}
|
|
2519
|
-
function buildPropertyRawValueOrTextTokenPredicate(params) {
|
|
2520
|
-
const { termsExpression, isCaseSensitive } = params;
|
|
2521
|
-
const rawValueQuery = `cts:element-attribute-word-query(
|
|
2522
|
-
xs:QName("value"),
|
|
2523
|
-
xs:QName("rawValue"),
|
|
2524
|
-
$term,
|
|
2525
|
-
${buildCtsQueryOptionsExpression(isCaseSensitive)}
|
|
2526
|
-
)`;
|
|
2527
|
-
const textQuery = `cts:element-word-query(
|
|
2528
|
-
xs:QName("value"),
|
|
2529
|
-
$term,
|
|
2530
|
-
${buildCtsQueryOptionsExpression(isCaseSensitive)}
|
|
2531
|
-
)`;
|
|
2532
|
-
return `(every $term in ${termsExpression}
|
|
2533
|
-
satisfies some $searchNode in (${buildPropertySimpleValueSearchableNodesExpression()})
|
|
2534
|
-
satisfies (
|
|
2535
|
-
cts:contains($searchNode, ${rawValueQuery})
|
|
2536
|
-
or
|
|
2537
|
-
cts:contains($searchNode, ${textQuery})
|
|
2538
|
-
))`;
|
|
2539
|
-
}
|
|
2540
2580
|
function getGroupableIncludesValue(query) {
|
|
2541
2581
|
switch (query.target) {
|
|
2542
2582
|
case "string":
|
|
@@ -2546,14 +2586,8 @@ function getGroupableIncludesValue(query) {
|
|
|
2546
2586
|
case "periods":
|
|
2547
2587
|
case "bibliography": return query.value;
|
|
2548
2588
|
case "property":
|
|
2549
|
-
if (query.dataType
|
|
2550
|
-
|
|
2551
|
-
return query.propertyValues[0] ?? null;
|
|
2552
|
-
}
|
|
2553
|
-
if (query.dataType === "IDREF") return null;
|
|
2554
|
-
if (query.dataType === "date" || query.dataType === "dateTime") return "value" in query && query.value != null ? query.value : null;
|
|
2555
|
-
if (query.propertyValues?.length !== 1) return null;
|
|
2556
|
-
return query.propertyValues[0] ?? null;
|
|
2589
|
+
if (query.dataType !== "string" || query.value == null) return null;
|
|
2590
|
+
return query.value;
|
|
2557
2591
|
}
|
|
2558
2592
|
}
|
|
2559
2593
|
function isCompatibleIncludesGroupQuery(params) {
|
|
@@ -2571,11 +2605,6 @@ function buildContentTargetIncludesGroupMember(params) {
|
|
|
2571
2605
|
matchMode: "includes",
|
|
2572
2606
|
isCaseSensitive
|
|
2573
2607
|
}),
|
|
2574
|
-
buildTokenPredicate: (termsExpression) => buildTokenizedSearchPredicate({
|
|
2575
|
-
searchableNodesExpression: buildSearchableContentNodesExpression(contentNodesExpression),
|
|
2576
|
-
termsExpression,
|
|
2577
|
-
isCaseSensitive
|
|
2578
|
-
}),
|
|
2579
2608
|
buildCandidateTermQuery: (termExpression) => buildContentTargetCandidateBranch({
|
|
2580
2609
|
containerElementName,
|
|
2581
2610
|
termExpression,
|
|
@@ -2592,11 +2621,6 @@ function buildItemStringIncludesGroupMember(query) {
|
|
|
2592
2621
|
matchMode: "includes",
|
|
2593
2622
|
isCaseSensitive: query.isCaseSensitive
|
|
2594
2623
|
}),
|
|
2595
|
-
buildTokenPredicate: (termsExpression) => buildTokenizedSearchPredicate({
|
|
2596
|
-
searchableNodesExpression: buildItemStringSearchableNodesExpression(query.language),
|
|
2597
|
-
termsExpression,
|
|
2598
|
-
isCaseSensitive: query.isCaseSensitive
|
|
2599
|
-
}),
|
|
2600
2624
|
buildCandidateTermQuery: (termExpression) => `cts:or-query((
|
|
2601
2625
|
${buildItemStringIdentificationBranch({
|
|
2602
2626
|
termExpression,
|
|
@@ -2614,22 +2638,18 @@ function buildItemStringIncludesGroupMember(query) {
|
|
|
2614
2638
|
function buildPropertyStringIncludesGroupMember(query) {
|
|
2615
2639
|
const propertyVariable = query.propertyVariable;
|
|
2616
2640
|
const predicateParts = [];
|
|
2617
|
-
const
|
|
2618
|
-
|
|
2619
|
-
|
|
2641
|
+
const valueExpression = buildPropertyValueContentValuesExpression({
|
|
2642
|
+
language: query.language,
|
|
2643
|
+
excludeInherited: true
|
|
2644
|
+
});
|
|
2620
2645
|
if (propertyVariable != null) predicateParts.push(buildPropertyLabelPredicate(propertyVariable));
|
|
2621
2646
|
return {
|
|
2622
2647
|
rawPredicate: buildPropertyPredicateExpression([...predicateParts, buildRawStringMatchPredicate({
|
|
2623
2648
|
valueExpression,
|
|
2624
|
-
value:
|
|
2649
|
+
value: query.value,
|
|
2625
2650
|
matchMode: "includes",
|
|
2626
2651
|
isCaseSensitive: query.isCaseSensitive
|
|
2627
2652
|
})]),
|
|
2628
|
-
buildTokenPredicate: (termsExpression) => buildPropertyPredicateExpression([...predicateParts, buildTokenizedSearchPredicate({
|
|
2629
|
-
searchableNodesExpression: buildSearchableContentNodesExpression(propertyContentNodesExpression),
|
|
2630
|
-
termsExpression,
|
|
2631
|
-
isCaseSensitive: query.isCaseSensitive
|
|
2632
|
-
})]),
|
|
2633
2653
|
buildCandidateTermQuery: (termExpression) => buildPropertyStringCandidateBranch({
|
|
2634
2654
|
termExpression,
|
|
2635
2655
|
isCaseSensitive: query.isCaseSensitive,
|
|
@@ -2637,31 +2657,6 @@ function buildPropertyStringIncludesGroupMember(query) {
|
|
|
2637
2657
|
})
|
|
2638
2658
|
};
|
|
2639
2659
|
}
|
|
2640
|
-
function buildPropertyRawValueOrTextIncludesGroupMember(query) {
|
|
2641
|
-
const propertyVariable = query.propertyVariable;
|
|
2642
|
-
const predicateParts = [];
|
|
2643
|
-
const propertyValue = getGroupableIncludesValue(query);
|
|
2644
|
-
if (propertyValue == null) throw new Error("Cannot build a rawValue/text includes group without a search value");
|
|
2645
|
-
if (propertyVariable != null) predicateParts.push(buildPropertyLabelPredicate(propertyVariable));
|
|
2646
|
-
return {
|
|
2647
|
-
rawPredicate: buildPropertyPredicateExpression([...predicateParts, buildPropertyRawValueOrTextRawPredicate({
|
|
2648
|
-
value: propertyValue,
|
|
2649
|
-
matchMode: "includes",
|
|
2650
|
-
isCaseSensitive: query.isCaseSensitive
|
|
2651
|
-
})]),
|
|
2652
|
-
buildTokenPredicate: (termsExpression) => buildPropertyPredicateExpression([...predicateParts, buildPropertyRawValueOrTextTokenPredicate({
|
|
2653
|
-
termsExpression,
|
|
2654
|
-
isCaseSensitive: query.isCaseSensitive
|
|
2655
|
-
})]),
|
|
2656
|
-
buildCandidateTermQuery: (termExpression) => buildOrCtsQueryExpression([buildPropertyRawValueCandidateBranch({
|
|
2657
|
-
termExpression,
|
|
2658
|
-
isCaseSensitive: query.isCaseSensitive
|
|
2659
|
-
}), buildPropertySimpleValueTextCandidateBranch({
|
|
2660
|
-
termExpression,
|
|
2661
|
-
isCaseSensitive: query.isCaseSensitive
|
|
2662
|
-
})])
|
|
2663
|
-
};
|
|
2664
|
-
}
|
|
2665
2660
|
function buildIncludesGroupMember(query) {
|
|
2666
2661
|
switch (query.target) {
|
|
2667
2662
|
case "string": return buildItemStringIncludesGroupMember(query);
|
|
@@ -2701,8 +2696,8 @@ function buildIncludesGroupMember(query) {
|
|
|
2701
2696
|
containerElementName: "image"
|
|
2702
2697
|
});
|
|
2703
2698
|
case "property":
|
|
2704
|
-
if (query.dataType === "
|
|
2705
|
-
return
|
|
2699
|
+
if (query.dataType === "all") throw new Error(`Property queries with dataType "all" are not compatible with includes-group optimization`);
|
|
2700
|
+
return buildPropertyStringIncludesGroupMember(query);
|
|
2706
2701
|
}
|
|
2707
2702
|
}
|
|
2708
2703
|
function getCompatibleIncludesGroupLeaves(params) {
|
|
@@ -2768,7 +2763,7 @@ function buildIncludesGroupClause(params) {
|
|
|
2768
2763
|
then cts:and-query(${termQueriesVar})
|
|
2769
2764
|
else ()`
|
|
2770
2765
|
],
|
|
2771
|
-
predicate:
|
|
2766
|
+
predicate: `cts:contains(., ${candidateQueryVar})`,
|
|
2772
2767
|
candidateQueryVar
|
|
2773
2768
|
};
|
|
2774
2769
|
}
|
|
@@ -2776,9 +2771,9 @@ function buildIncludesGroupClause(params) {
|
|
|
2776
2771
|
* Build a string match predicate for an XQuery string.
|
|
2777
2772
|
*/
|
|
2778
2773
|
function buildStringMatchClause(params) {
|
|
2779
|
-
const { contentNodesExpression, value, matchMode, isCaseSensitive, version, queryKey, buildCandidateTermQuery } = params;
|
|
2774
|
+
const { contentNodesExpression, value, matchMode, isCaseSensitive, version, queryKey, allowCtsPredicates, buildCandidateTermQuery } = params;
|
|
2780
2775
|
const valueExpression = buildFlattenedContentValuesExpression(contentNodesExpression);
|
|
2781
|
-
if (matchMode === "includes" && version === 2 && buildCandidateTermQuery != null) return buildCtsIncludesPredicate({
|
|
2776
|
+
if (allowCtsPredicates && matchMode === "includes" && version === 2 && buildCandidateTermQuery != null) return buildCtsIncludesPredicate({
|
|
2782
2777
|
searchableNodesExpression: buildSearchableContentNodesExpression(contentNodesExpression),
|
|
2783
2778
|
fallbackValueExpression: valueExpression,
|
|
2784
2779
|
value,
|
|
@@ -2797,163 +2792,113 @@ function buildStringMatchClause(params) {
|
|
|
2797
2792
|
candidateQueryVar: null
|
|
2798
2793
|
};
|
|
2799
2794
|
}
|
|
2800
|
-
function
|
|
2801
|
-
const {
|
|
2802
|
-
const
|
|
2803
|
-
|
|
2804
|
-
return buildOrPredicate(valuePredicates);
|
|
2805
|
-
}
|
|
2806
|
-
function buildPropertyRawValueOrTextMatchClause(params) {
|
|
2807
|
-
const { value, matchMode, isCaseSensitive, version, queryKey } = params;
|
|
2808
|
-
const fallbackPredicate = buildPropertyRawValueOrTextRawPredicate({
|
|
2795
|
+
function buildCombinedRawStringMatchClause(params) {
|
|
2796
|
+
const { valueExpressions, value, matchMode, isCaseSensitive, version, queryKey, allowCtsPredicates, buildCandidateTermQuery } = params;
|
|
2797
|
+
const predicate = buildCombinedRawStringMatchPredicate({
|
|
2798
|
+
valueExpressions,
|
|
2809
2799
|
value,
|
|
2810
2800
|
matchMode,
|
|
2811
2801
|
isCaseSensitive
|
|
2812
2802
|
});
|
|
2813
|
-
if (matchMode
|
|
2814
|
-
|
|
2815
|
-
predicate: fallbackPredicate,
|
|
2816
|
-
candidateQueryVar: null
|
|
2817
|
-
};
|
|
2818
|
-
const tokenizedSearchDeclarations = buildTokenizedSearchDeclarations({
|
|
2819
|
-
value,
|
|
2820
|
-
isCaseSensitive,
|
|
2821
|
-
queryKey
|
|
2822
|
-
});
|
|
2823
|
-
const tokenizedTerms = tokenizeIncludesSearchValue({
|
|
2824
|
-
value,
|
|
2825
|
-
isCaseSensitive
|
|
2826
|
-
});
|
|
2827
|
-
const termQueriesVar = `$query${queryKey}TermQueries`;
|
|
2828
|
-
const candidateQueryVar = `$query${queryKey}CandidateQuery`;
|
|
2829
|
-
if (tokenizedTerms.length === 0) return {
|
|
2830
|
-
declarations: [],
|
|
2831
|
-
predicate: fallbackPredicate,
|
|
2832
|
-
candidateQueryVar: null
|
|
2833
|
-
};
|
|
2834
|
-
return {
|
|
2835
|
-
declarations: [
|
|
2836
|
-
...tokenizedSearchDeclarations.declarations,
|
|
2837
|
-
`let ${termQueriesVar} :=
|
|
2838
|
-
for $term in ${tokenizedSearchDeclarations.termsVar}
|
|
2839
|
-
return ${buildOrCtsQueryExpression([buildPropertyRawValueCandidateBranch({
|
|
2840
|
-
termExpression: "$term",
|
|
2841
|
-
isCaseSensitive
|
|
2842
|
-
}), buildPropertySimpleValueTextCandidateBranch({
|
|
2843
|
-
termExpression: "$term",
|
|
2844
|
-
isCaseSensitive
|
|
2845
|
-
})])}`,
|
|
2846
|
-
`let ${candidateQueryVar} :=
|
|
2847
|
-
if (count(${tokenizedSearchDeclarations.termsVar}) = 1)
|
|
2848
|
-
then ${termQueriesVar}[1]
|
|
2849
|
-
else if (count(${tokenizedSearchDeclarations.termsVar}) gt 1)
|
|
2850
|
-
then cts:and-query(${termQueriesVar})
|
|
2851
|
-
else ()`
|
|
2852
|
-
],
|
|
2853
|
-
predicate: buildPropertyRawValueOrTextTokenPredicate({
|
|
2854
|
-
termsExpression: tokenizedSearchDeclarations.termsVar,
|
|
2855
|
-
isCaseSensitive
|
|
2856
|
-
}),
|
|
2857
|
-
candidateQueryVar
|
|
2858
|
-
};
|
|
2859
|
-
}
|
|
2860
|
-
function buildPropertyRawValueOrTextClause(params) {
|
|
2861
|
-
const { values, matchMode, isCaseSensitive, version, queryKey } = params;
|
|
2862
|
-
const declarations = [];
|
|
2863
|
-
const valuePredicates = [];
|
|
2864
|
-
const candidateQueryVars = [];
|
|
2865
|
-
for (const [valueIndex, value] of values.entries()) {
|
|
2866
|
-
const compiledClause = buildPropertyRawValueOrTextMatchClause({
|
|
2803
|
+
if (allowCtsPredicates && matchMode === "includes" && version === 2 && buildCandidateTermQuery != null) {
|
|
2804
|
+
const candidateQuery = buildCtsCandidateQuery({
|
|
2867
2805
|
value,
|
|
2868
|
-
matchMode,
|
|
2869
2806
|
isCaseSensitive,
|
|
2870
|
-
|
|
2871
|
-
|
|
2807
|
+
queryKey,
|
|
2808
|
+
buildCandidateTermQuery
|
|
2872
2809
|
});
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
if (candidateQueryVars.length > 0) {
|
|
2879
|
-
const candidateQueriesExpression = `(${candidateQueryVars.join(", ")})`;
|
|
2880
|
-
candidateQueryVar = `$query${queryKey}CandidateQuery`;
|
|
2881
|
-
declarations.push(`let ${candidateQueryVar} :=
|
|
2882
|
-
if (count(${candidateQueriesExpression}) = 1)
|
|
2883
|
-
then ${candidateQueriesExpression}[1]
|
|
2884
|
-
else if (count(${candidateQueriesExpression}) gt 1)
|
|
2885
|
-
then cts:or-query(${candidateQueriesExpression})
|
|
2886
|
-
else ()`);
|
|
2810
|
+
return {
|
|
2811
|
+
declarations: candidateQuery.declarations,
|
|
2812
|
+
predicate,
|
|
2813
|
+
candidateQueryVar: candidateQuery.candidateQueryVar
|
|
2814
|
+
};
|
|
2887
2815
|
}
|
|
2888
2816
|
return {
|
|
2889
|
-
declarations,
|
|
2890
|
-
predicate
|
|
2891
|
-
candidateQueryVar
|
|
2817
|
+
declarations: [],
|
|
2818
|
+
predicate,
|
|
2819
|
+
candidateQueryVar: null
|
|
2892
2820
|
};
|
|
2893
2821
|
}
|
|
2822
|
+
function buildPropertyValueAttributePredicate(params) {
|
|
2823
|
+
const { propertyValue, attributeName } = params;
|
|
2824
|
+
return `value[@${attributeName}=${stringLiteral(propertyValue)}]`;
|
|
2825
|
+
}
|
|
2894
2826
|
function buildPropertyPredicateExpression(propertyPredicates) {
|
|
2895
2827
|
let propertyExpression = ".//properties//property";
|
|
2896
2828
|
for (const propertyPredicate of propertyPredicates) propertyExpression += `[${propertyPredicate}]`;
|
|
2897
2829
|
return propertyExpression;
|
|
2898
2830
|
}
|
|
2899
2831
|
function buildPropertyStringValueClause(params) {
|
|
2900
|
-
const { query, version, queryKey } = params;
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2832
|
+
const { query, version, queryKey, allowCtsPredicates } = params;
|
|
2833
|
+
return buildStringMatchClause({
|
|
2834
|
+
contentNodesExpression: buildPropertyValueContentNodesExpression({
|
|
2835
|
+
language: query.language,
|
|
2836
|
+
excludeInherited: allowCtsPredicates && query.matchMode === "includes" && version === 2
|
|
2837
|
+
}),
|
|
2838
|
+
value: query.value,
|
|
2839
|
+
matchMode: query.matchMode,
|
|
2840
|
+
isCaseSensitive: query.isCaseSensitive,
|
|
2841
|
+
version,
|
|
2842
|
+
queryKey,
|
|
2843
|
+
allowCtsPredicates,
|
|
2844
|
+
buildCandidateTermQuery: (termExpression) => buildPropertyStringCandidateBranch({
|
|
2845
|
+
termExpression,
|
|
2910
2846
|
isCaseSensitive: query.isCaseSensitive,
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
else ()`);
|
|
2933
|
-
}
|
|
2847
|
+
language: query.language
|
|
2848
|
+
})
|
|
2849
|
+
});
|
|
2850
|
+
}
|
|
2851
|
+
function buildPropertyScalarValueClause(params) {
|
|
2852
|
+
const { value, matchMode, isCaseSensitive, version, queryKey, allowCtsPredicates } = params;
|
|
2853
|
+
return buildCombinedRawStringMatchClause({
|
|
2854
|
+
valueExpressions: buildPropertyScalarValueExpressions(),
|
|
2855
|
+
value,
|
|
2856
|
+
matchMode,
|
|
2857
|
+
isCaseSensitive,
|
|
2858
|
+
version,
|
|
2859
|
+
queryKey,
|
|
2860
|
+
allowCtsPredicates,
|
|
2861
|
+
buildCandidateTermQuery: (termExpression) => buildPropertyScalarCandidateBranch({
|
|
2862
|
+
termExpression,
|
|
2863
|
+
isCaseSensitive
|
|
2864
|
+
})
|
|
2865
|
+
});
|
|
2866
|
+
}
|
|
2867
|
+
function buildPropertyAllValueClause(query) {
|
|
2934
2868
|
return {
|
|
2935
|
-
declarations,
|
|
2936
|
-
predicate:
|
|
2937
|
-
|
|
2869
|
+
declarations: [],
|
|
2870
|
+
predicate: buildCombinedRawStringMatchPredicate({
|
|
2871
|
+
valueExpressions: buildAllPropertyValueExpressions(query.language),
|
|
2872
|
+
value: query.value,
|
|
2873
|
+
matchMode: query.matchMode,
|
|
2874
|
+
isCaseSensitive: query.isCaseSensitive
|
|
2875
|
+
}),
|
|
2876
|
+
candidateQueryVar: null
|
|
2938
2877
|
};
|
|
2939
2878
|
}
|
|
2940
2879
|
/**
|
|
2941
2880
|
* Build a property predicate for an XQuery string.
|
|
2942
2881
|
*/
|
|
2943
2882
|
function buildPropertyClause(params) {
|
|
2944
|
-
const { query, version, queryKey } = params;
|
|
2883
|
+
const { query, version, queryKey, allowCtsPredicates } = params;
|
|
2945
2884
|
const predicateParts = [];
|
|
2946
2885
|
const declarations = [];
|
|
2947
2886
|
const propertyVariable = query.propertyVariable;
|
|
2948
2887
|
let candidateQueryVar = null;
|
|
2949
2888
|
if (propertyVariable != null) predicateParts.push(buildPropertyLabelPredicate(propertyVariable));
|
|
2950
|
-
if (query.dataType === "
|
|
2951
|
-
const
|
|
2952
|
-
|
|
2889
|
+
if (query.dataType === "all") {
|
|
2890
|
+
const compiledAllClause = buildPropertyAllValueClause(query);
|
|
2891
|
+
declarations.push(...compiledAllClause.declarations);
|
|
2892
|
+
predicateParts.push(compiledAllClause.predicate);
|
|
2893
|
+
candidateQueryVar = compiledAllClause.candidateQueryVar;
|
|
2894
|
+
} else if (query.dataType === "date" || query.dataType === "dateTime") if ("value" in query && query.value != null) {
|
|
2895
|
+
const compiledScalarClause = buildPropertyScalarValueClause({
|
|
2896
|
+
value: query.value,
|
|
2953
2897
|
matchMode: query.matchMode,
|
|
2954
2898
|
isCaseSensitive: query.isCaseSensitive,
|
|
2955
2899
|
version,
|
|
2956
|
-
queryKey
|
|
2900
|
+
queryKey,
|
|
2901
|
+
allowCtsPredicates
|
|
2957
2902
|
});
|
|
2958
2903
|
declarations.push(...compiledScalarClause.declarations);
|
|
2959
2904
|
predicateParts.push(compiledScalarClause.predicate);
|
|
@@ -2962,10 +2907,10 @@ function buildPropertyClause(params) {
|
|
|
2962
2907
|
from: query.from,
|
|
2963
2908
|
to: query.to
|
|
2964
2909
|
}));
|
|
2965
|
-
else if (query.
|
|
2910
|
+
else if (query.value != null) switch (query.dataType) {
|
|
2966
2911
|
case "IDREF":
|
|
2967
2912
|
predicateParts.push(buildPropertyValueAttributePredicate({
|
|
2968
|
-
|
|
2913
|
+
propertyValue: query.value,
|
|
2969
2914
|
attributeName: "uuid"
|
|
2970
2915
|
}));
|
|
2971
2916
|
break;
|
|
@@ -2973,12 +2918,13 @@ function buildPropertyClause(params) {
|
|
|
2973
2918
|
case "decimal":
|
|
2974
2919
|
case "time":
|
|
2975
2920
|
case "boolean": {
|
|
2976
|
-
const compiledScalarClause =
|
|
2977
|
-
|
|
2921
|
+
const compiledScalarClause = buildPropertyScalarValueClause({
|
|
2922
|
+
value: query.value,
|
|
2978
2923
|
matchMode: query.matchMode,
|
|
2979
2924
|
isCaseSensitive: query.isCaseSensitive,
|
|
2980
2925
|
version,
|
|
2981
|
-
queryKey
|
|
2926
|
+
queryKey,
|
|
2927
|
+
allowCtsPredicates
|
|
2982
2928
|
});
|
|
2983
2929
|
declarations.push(...compiledScalarClause.declarations);
|
|
2984
2930
|
predicateParts.push(compiledScalarClause.predicate);
|
|
@@ -2989,7 +2935,8 @@ function buildPropertyClause(params) {
|
|
|
2989
2935
|
const compiledStringClause = buildPropertyStringValueClause({
|
|
2990
2936
|
query,
|
|
2991
2937
|
version,
|
|
2992
|
-
queryKey
|
|
2938
|
+
queryKey,
|
|
2939
|
+
allowCtsPredicates
|
|
2993
2940
|
});
|
|
2994
2941
|
declarations.push(...compiledStringClause.declarations);
|
|
2995
2942
|
predicateParts.push(compiledStringClause.predicate);
|
|
@@ -3007,12 +2954,13 @@ function buildPropertyClause(params) {
|
|
|
3007
2954
|
* Build a query predicate for an XQuery string.
|
|
3008
2955
|
*/
|
|
3009
2956
|
function buildQueryClause(params) {
|
|
3010
|
-
const { query, version, queryKey } = params;
|
|
2957
|
+
const { query, version, queryKey, allowCtsPredicates } = params;
|
|
3011
2958
|
switch (query.target) {
|
|
3012
2959
|
case "string": return buildItemStringSearchClause({
|
|
3013
2960
|
query,
|
|
3014
2961
|
version,
|
|
3015
|
-
queryKey
|
|
2962
|
+
queryKey,
|
|
2963
|
+
allowCtsPredicates
|
|
3016
2964
|
});
|
|
3017
2965
|
case "title": return buildStringMatchClause({
|
|
3018
2966
|
contentNodesExpression: `identification/label/content[@xml:lang="${query.language}"]`,
|
|
@@ -3021,6 +2969,7 @@ function buildQueryClause(params) {
|
|
|
3021
2969
|
isCaseSensitive: query.isCaseSensitive,
|
|
3022
2970
|
version,
|
|
3023
2971
|
queryKey,
|
|
2972
|
+
allowCtsPredicates,
|
|
3024
2973
|
buildCandidateTermQuery: (termExpression) => buildContentTargetCandidateBranch({
|
|
3025
2974
|
containerElementName: "identification",
|
|
3026
2975
|
termExpression,
|
|
@@ -3035,6 +2984,7 @@ function buildQueryClause(params) {
|
|
|
3035
2984
|
isCaseSensitive: query.isCaseSensitive,
|
|
3036
2985
|
version,
|
|
3037
2986
|
queryKey,
|
|
2987
|
+
allowCtsPredicates,
|
|
3038
2988
|
buildCandidateTermQuery: (termExpression) => buildContentTargetCandidateBranch({
|
|
3039
2989
|
containerElementName: "description",
|
|
3040
2990
|
termExpression,
|
|
@@ -3049,6 +2999,7 @@ function buildQueryClause(params) {
|
|
|
3049
2999
|
isCaseSensitive: query.isCaseSensitive,
|
|
3050
3000
|
version,
|
|
3051
3001
|
queryKey,
|
|
3002
|
+
allowCtsPredicates,
|
|
3052
3003
|
buildCandidateTermQuery: (termExpression) => buildContentTargetCandidateBranch({
|
|
3053
3004
|
containerElementName: "period",
|
|
3054
3005
|
termExpression,
|
|
@@ -3063,6 +3014,7 @@ function buildQueryClause(params) {
|
|
|
3063
3014
|
isCaseSensitive: query.isCaseSensitive,
|
|
3064
3015
|
version,
|
|
3065
3016
|
queryKey,
|
|
3017
|
+
allowCtsPredicates,
|
|
3066
3018
|
buildCandidateTermQuery: (termExpression) => buildContentTargetCandidateBranch({
|
|
3067
3019
|
containerElementName: "bibliography",
|
|
3068
3020
|
termExpression,
|
|
@@ -3077,6 +3029,7 @@ function buildQueryClause(params) {
|
|
|
3077
3029
|
isCaseSensitive: query.isCaseSensitive,
|
|
3078
3030
|
version,
|
|
3079
3031
|
queryKey,
|
|
3032
|
+
allowCtsPredicates,
|
|
3080
3033
|
buildCandidateTermQuery: (termExpression) => buildContentTargetCandidateBranch({
|
|
3081
3034
|
containerElementName: "image",
|
|
3082
3035
|
termExpression,
|
|
@@ -3087,7 +3040,8 @@ function buildQueryClause(params) {
|
|
|
3087
3040
|
case "property": return buildPropertyClause({
|
|
3088
3041
|
query,
|
|
3089
3042
|
version,
|
|
3090
|
-
queryKey
|
|
3043
|
+
queryKey,
|
|
3044
|
+
allowCtsPredicates
|
|
3091
3045
|
});
|
|
3092
3046
|
}
|
|
3093
3047
|
}
|
|
@@ -3095,11 +3049,12 @@ function buildQueryClause(params) {
|
|
|
3095
3049
|
* Build a boolean query clause for an XQuery string.
|
|
3096
3050
|
*/
|
|
3097
3051
|
function buildBooleanQueryNode(params) {
|
|
3098
|
-
const { query, version, queryKey } = params;
|
|
3052
|
+
const { query, version, queryKey, allowCtsPredicates } = params;
|
|
3099
3053
|
const compiledQueryClause = buildQueryClause({
|
|
3100
3054
|
query,
|
|
3101
3055
|
version,
|
|
3102
|
-
queryKey
|
|
3056
|
+
queryKey,
|
|
3057
|
+
allowCtsPredicates
|
|
3103
3058
|
});
|
|
3104
3059
|
const baseClause = `(${compiledQueryClause.predicate})`;
|
|
3105
3060
|
return {
|
|
@@ -3109,11 +3064,12 @@ function buildBooleanQueryNode(params) {
|
|
|
3109
3064
|
};
|
|
3110
3065
|
}
|
|
3111
3066
|
function buildQueryNode(params) {
|
|
3112
|
-
const { query, version, queryKey } = params;
|
|
3067
|
+
const { query, version, queryKey, allowCtsPredicates } = params;
|
|
3113
3068
|
if (isQueryLeaf(query)) return buildBooleanQueryNode({
|
|
3114
3069
|
query,
|
|
3115
3070
|
version,
|
|
3116
|
-
queryKey
|
|
3071
|
+
queryKey,
|
|
3072
|
+
allowCtsPredicates
|
|
3117
3073
|
});
|
|
3118
3074
|
const groupQueries = getQueryGroupChildren(query);
|
|
3119
3075
|
const optimizedIncludesGroupQueries = getCompatibleIncludesGroupLeaves({
|
|
@@ -3130,10 +3086,11 @@ function buildQueryNode(params) {
|
|
|
3130
3086
|
return buildQueryNode({
|
|
3131
3087
|
query: onlyQuery,
|
|
3132
3088
|
version,
|
|
3133
|
-
queryKey
|
|
3089
|
+
queryKey,
|
|
3090
|
+
allowCtsPredicates
|
|
3134
3091
|
});
|
|
3135
3092
|
}
|
|
3136
|
-
if (optimizedIncludesGroupQueries != null) {
|
|
3093
|
+
if (allowCtsPredicates && optimizedIncludesGroupQueries != null) {
|
|
3137
3094
|
const compiledClause = buildIncludesGroupClause({
|
|
3138
3095
|
queries: optimizedIncludesGroupQueries,
|
|
3139
3096
|
queryKey
|
|
@@ -3146,20 +3103,29 @@ function buildQueryNode(params) {
|
|
|
3146
3103
|
}
|
|
3147
3104
|
const declarations = [];
|
|
3148
3105
|
const predicates = [];
|
|
3149
|
-
const
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3106
|
+
const groupOperator = getQueryGroupOperator(query);
|
|
3107
|
+
let compiledChildNodes = groupQueries.map((groupQuery, groupIndex) => buildQueryNode({
|
|
3108
|
+
query: groupQuery,
|
|
3109
|
+
version,
|
|
3110
|
+
queryKey: `${queryKey}_${groupIndex + 1}`,
|
|
3111
|
+
allowCtsPredicates
|
|
3112
|
+
}));
|
|
3113
|
+
if (allowCtsPredicates && groupOperator === "or" && compiledChildNodes.some((node) => node.candidateQueryVars.length === 0)) compiledChildNodes = groupQueries.map((groupQuery, groupIndex) => buildQueryNode({
|
|
3114
|
+
query: groupQuery,
|
|
3115
|
+
version,
|
|
3116
|
+
queryKey: `${queryKey}_${groupIndex + 1}`,
|
|
3117
|
+
allowCtsPredicates: false
|
|
3118
|
+
}));
|
|
3119
|
+
const candidateQueryVarsByChild = [];
|
|
3120
|
+
for (const compiledQueryNode of compiledChildNodes) {
|
|
3156
3121
|
declarations.push(...compiledQueryNode.declarations);
|
|
3157
3122
|
predicates.push(compiledQueryNode.predicate);
|
|
3158
|
-
|
|
3123
|
+
candidateQueryVarsByChild.push(compiledQueryNode.candidateQueryVars);
|
|
3159
3124
|
}
|
|
3125
|
+
const candidateQueryVars = groupOperator === "and" ? candidateQueryVarsByChild.flat() : candidateQueryVarsByChild.every((vars) => vars.length > 0) ? candidateQueryVarsByChild.flat() : [];
|
|
3160
3126
|
return {
|
|
3161
3127
|
declarations,
|
|
3162
|
-
predicate:
|
|
3128
|
+
predicate: groupOperator === "and" ? buildAndPredicate(predicates) : buildOrPredicate(predicates),
|
|
3163
3129
|
candidateQueryVars
|
|
3164
3130
|
};
|
|
3165
3131
|
}
|
|
@@ -3172,7 +3138,8 @@ function buildQueryPlan(params) {
|
|
|
3172
3138
|
const compiledQueryNode = buildQueryNode({
|
|
3173
3139
|
query: queries,
|
|
3174
3140
|
version,
|
|
3175
|
-
queryKey: "1"
|
|
3141
|
+
queryKey: "1",
|
|
3142
|
+
allowCtsPredicates: true
|
|
3176
3143
|
});
|
|
3177
3144
|
if (compiledQueryNode.declarations.length > 0) declarations.push(`let ${CTS_INCLUDES_STOP_WORDS_VAR} := (${CTS_INCLUDES_STOP_WORDS.map((stopWord) => stringLiteral(stopWord)).join(", ")})`, ...compiledQueryNode.declarations);
|
|
3178
3145
|
predicate = compiledQueryNode.predicate;
|
|
@@ -3353,7 +3320,7 @@ async function fetchSetItems(params, itemCategories, options) {
|
|
|
3353
3320
|
else response = await (options?.fetch ?? fetch)(`https://ochre.lib.uchicago.edu/ochre?xquery=${encodeURIComponent(xquery)}&format=json&lang="*"`);
|
|
3354
3321
|
if (!response.ok) throw new Error(`OCHRE API responded with status: ${response.status}`);
|
|
3355
3322
|
const data = await response.json();
|
|
3356
|
-
if (Array.isArray(data.result) || Object.keys(data.result).length === 0) throw new Error("
|
|
3323
|
+
if (Array.isArray(data.result) || Object.keys(data.result).length === 0) throw new Error("Invalid OCHRE API response");
|
|
3357
3324
|
if (itemCategories != null) {
|
|
3358
3325
|
const itemCategoriesSet = new Set(Object.keys(data.result.ochre.items));
|
|
3359
3326
|
const missingCategories = itemCategories.filter((category) => !itemCategoriesSet.has(category));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ochre-sdk",
|
|
3
|
-
"version": "0.21.
|
|
3
|
+
"version": "0.21.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Node.js library for working with OCHRE (Online Cultural and Historical Research Environment) data",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"zod": "^4.3.6"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@antfu/eslint-config": "^
|
|
50
|
-
"@types/node": "^24.12.
|
|
49
|
+
"@antfu/eslint-config": "^8.0.0",
|
|
50
|
+
"@types/node": "^24.12.2",
|
|
51
51
|
"bumpp": "^11.0.1",
|
|
52
52
|
"eslint": "^10.1.0",
|
|
53
53
|
"prettier": "^3.8.1",
|