-
Notifications
You must be signed in to change notification settings - Fork 2
/
indexComparisonChecks.js
173 lines (151 loc) · 5.49 KB
/
indexComparisonChecks.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/*
* *Partially* checks for:
*
* 1. Fields and field range indexes the code is dependent on but not defined by the database.
* 2. Fields and field range indexes the code is not dependent on but are defined by the database.
*
* Known limitations:
*
* 1. Excludes value of the fullTextSearchRelatedFieldName property (for keyword search).
* 2. Excludes indexes referenced in data constant configuration files, specifically the call to
* cts.fieldReference('languageIdentifier') from within languages.mjs.
* 3. Excludes references in the configuration of Similar search terms. Technically, Similar does
* not use the indexes but instead snags XPath expressions from the index configuration; thus,
* unless/until Similar can get the XPaths elsewhere, the associated indexes are required.
*
* Individual field and field range index settings are not checked.
*
* Run as an admin or lux-endpoint-consumer to ensure getSearchTermsConfig() returns all search terms.
*/
/*
* COLLECT: CONFIGURED
*/
const databaseName = 'lux-content';
const includeAutoComplete = true;
const admin = require('/MarkLogic/admin.xqy');
const config = admin.getConfiguration();
const configuredFieldNames = [];
let nodes = admin
.databaseGetFields(config, xdmp.database(databaseName))
.toArray();
nodes.forEach((node) => {
const name = node.xpath('field-name/text()').toString();
if (name.length > 0) {
configuredFieldNames.push(name);
}
});
const configuredFieldRangeNames = [];
nodes = admin
.databaseGetRangeFieldIndexes(config, xdmp.database(databaseName))
.toArray();
nodes.forEach((node) => {
const name = node.xpath('field-name/text()').toString();
if (name.length > 0) {
configuredFieldRangeNames.push(name);
}
});
/*
* COLLECT: REFERENCED
*/
import * as utils from '/utils/utils.mjs';
import {
getConfigurationByContext,
getContextParameterValues,
} from '../config/autoCompleteConfig.mjs';
import { FACETS_CONFIG } from '../../config/facetsConfig.mjs';
import { getSearchTermsConfig } from '../../config/searchTermsConfig.mjs';
import { SORT_BINDINGS } from '../../config/searchResultsSortConfig.mjs';
const searchTermsConfig = getSearchTermsConfig();
const referenced = {
fields: {},
fieldRanges: {},
};
const recordReference = (name, isRange, context) => {
const typeKey = isRange ? 'fieldRanges' : 'fields';
if (!referenced[typeKey][name]) {
referenced[typeKey][name] = [context];
} else if (!referenced[typeKey][name].includes(context)) {
referenced[typeKey][name].push(context);
}
};
if (includeAutoComplete) {
const recordAutoCompleteReference = (name) => {
if (name != null) {
recordReference(name, true, 'auto complete');
if (name.includes('Primary')) {
recordReference(name.replace('Primary', ''), true, 'auto complete');
}
}
};
getContextParameterValues().forEach((autoCompleteContext) => {
const autoCompleteConfig = getConfigurationByContext(autoCompleteContext);
recordAutoCompleteReference(autoCompleteConfig.namesIndexReference);
if (utils.isNonEmptyArray(autoCompleteConfig.idsIndexReferences)) {
autoCompleteConfig.idsIndexReferences.forEach((name) => {
recordAutoCompleteReference(name);
});
}
});
}
Object.keys(FACETS_CONFIG).forEach((key) => {
recordReference(FACETS_CONFIG[key].indexReference, true, 'facet');
});
Object.keys(SORT_BINDINGS).forEach((key) => {
recordReference(SORT_BINDINGS[key].indexReference, true, 'sort');
});
Object.keys(searchTermsConfig).forEach((searchScope) => {
Object.keys(searchTermsConfig[searchScope]).forEach((termName) => {
const term = searchTermsConfig[searchScope][termName];
if (term.indexReferences) {
term.indexReferences.forEach((name) => {
const isRange =
!name.endsWith('Text') &&
!name.endsWith('Name') &&
name != 'placeSpatial';
recordReference(name, isRange, 'search');
});
}
if (term.idIndexReferences) {
term.idIndexReferences.forEach((name) => {
recordReference(name, true, 'search');
});
}
});
});
const referencedFieldRangeNames = Object.keys(referenced.fieldRanges).sort();
let referencedFieldNames = Object.keys(referenced.fields);
// A field range index cannot exist without a field, but the code may only use the field range index.
referencedFieldRangeNames.forEach((name) => {
if (!referencedFieldNames.includes(name)) {
referencedFieldNames.push(name);
}
});
referencedFieldNames = referencedFieldNames.sort();
/*
* COMPARE
*/
// const configuredFieldsNotAlsoRanges = utils.getArrayDiff(configuredFieldNames, configuredFieldRangeNames).sort()
// const referencedFieldsNotAlsoRanges = utils.getArrayDiff(referencedFieldNames, referencedFieldRangeNames).sort()
const missingFields = utils
.getArrayDiff(referencedFieldNames, configuredFieldNames)
.sort();
const unusedFields = utils
.getArrayDiff(configuredFieldNames, referencedFieldNames)
.sort();
const missingFieldRanges = utils
.getArrayDiff(referencedFieldRangeNames, configuredFieldRangeNames)
.sort();
const unusedFieldRanges = utils
.getArrayDiff(configuredFieldRangeNames, referencedFieldRangeNames)
.sort();
const results = {
missing: {
fields: missingFields,
fieldRanges: missingFieldRanges,
},
unused: {
fields: unusedFields,
fieldRanges: unusedFieldRanges,
},
};
results;