Skip to content

Commit a8ca30b

Browse files
committed
edit: optionalized query.key to accept string array
1 parent 0549519 commit a8ca30b

File tree

4 files changed

+88
-86
lines changed

4 files changed

+88
-86
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ also accommodate multiple key searches.
8888
___
8989
## setup
9090
91-
1) running generated AQL queries will require a running arangodb instance.
91+
1) running generated AQL queries will require a running ArangoDB v3.6+
92+
instance. This package is tested against v3.6.5 🥑
9293
9394
## installation
9495
currently there is only support for server-side use.
@@ -97,7 +98,8 @@ currently there is only support for server-side use.
9798
or `npm install --save @hp4k1h5/AQLqueryBuilder.js`
9899
in a directory containing a `package.json` file.
99100
__or__
100-
clone this repository in your node compatible project.
101+
clone this repository in your node compatible project. And run `yarn` from
102+
inside the directory.
101103
102104
2) import/require the exported functions
103105
```js

src/lib/structs.ts

Lines changed: 64 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,91 @@
11
/**
2-
* passed to buildAQL, i.e. `let generatedAQL = buildAQL(query)`. Properties
3-
* mimic or match those familiar to AQL.
4-
* */
2+
* passed to buildAQL, i.e. `let generatedAQL = buildAQL(query)`. Properties
3+
* mimic or match those familiar to AQL.
4+
* */
55
export interface query {
66
/**
7-
* the name of the ArangoSearch View the query will be run against
8-
* */
9-
view: string,
7+
* the name of the ArangoSearch View the query will be run against
8+
* */
9+
view: string
1010
/**
11-
* the names of the collections indexed by @param view to query
12-
* */
13-
collections: collection[],
11+
* the names of the collections indexed by @param view to query
12+
* */
13+
collections: collection[]
1414
/**
15-
* either an array of @param term interfaces or a string to be parsed by `parseQuery()`
16-
* */
17-
terms: term[] | string,
15+
* either an array of @param term interfaces or a string to be parsed by `parseQuery()`
16+
* */
17+
terms: term[] | string
1818
/**
19-
* the name of the document key to search, currently must be the same across
20-
* all documents. @default "text"
21-
* */
22-
key?: string,
19+
* the name of the document key to search, currently must be the same across
20+
* all documents. @default "text"
21+
* */
22+
key?: string
2323
/**
24-
* a list of @filter interfaces. All filters are implicitly AND'ed together.
25-
* */
26-
filters?: filter[],
24+
* a list of @filter interfaces. All filters are implicitly AND'ed together.
25+
* */
26+
filters?: filter[]
2727
}
2828

2929
/**
30-
* Each collection referenced by the ArangoSearch that the user wishes to
31-
* include in the query must be listed as a collection of the following shape.
32-
*
33-
* A collection can be referenced by several analyzers and each must have its
34-
* own entry in `query.collections` in order to be included in the search.
35-
*
36-
* Alternatively, a document can be stored in several collections.
37-
*
38-
* In either case all desired collection/analyzer combinations must be
39-
* specified.
40-
* */
30+
* Each collection referenced by the ArangoSearch that the user wishes to
31+
* include in the query must be listed as a collection of the following shape.
32+
*
33+
* A collection can be referenced by several analyzers and each must have its
34+
* own entry in `query.collections` in order to be included in the search.
35+
*
36+
* Alternatively, a document can be stored in several collections.
37+
*
38+
* In either case all desired collection/analyzer combinations must be
39+
* specified.
40+
* */
4141
export interface collection {
4242
/**
43-
* the name of the collection
44-
* */
45-
name: string,
43+
* the name of the collection
44+
* */
45+
name: string
4646
/**
47-
* the name of the text analyzer
48-
* */
49-
analyzer: string,
47+
* the name of the text analyzer
48+
* */
49+
analyzer: string
5050
}
5151

5252
/**
53-
* A piece of search query text. Can be a phrase or an individual word, and will
54-
* belong to one cell or other of the following grid:
55-
* ```
56-
* **ops**
57-
* | | ANDS | ORS | NOTS |
58-
* | ----- | ---- | --- | ----- |
59-
* **types** | PHRASE | | | |
60-
* | TOKENS | | | |
61-
* | PROXIM | TODO | TODO| TODO |
62-
* ```
63-
* */
53+
* A piece of search query text. Can be a phrase or an individual word, and will
54+
* belong to one cell or other of the following grid:
55+
* ```
56+
* **ops**
57+
* | | ANDS | ORS | NOTS |
58+
* | ----- | ---- | --- | ----- |
59+
* **types** | PHRASE | ✅ | ✅ | |
60+
* | TOKENS | ✅ | ✅ | |
61+
* | PROXIM | TODO | TODO| TODO |
62+
* ```
63+
* */
6464
export interface term {
65-
/**
66-
* must be one of [ 'phr', 'tok' ], corresponding to `PHRASE` and
67-
* `TOKENS` respectively.
68-
**/
69-
type: string,
7065
/**
71-
* the search string
72-
* */
73-
val: string,
66+
* must be one of [ 'phr', 'tok' ], corresponding to `PHRASE` and
67+
* `TOKENS` respectively.
68+
**/
69+
type: string
7470
/**
75-
* must be one of [ '+', '?', '-' ] corresponding to `ANDS`, `ORS`, and
76-
* `NOTS`, respectively.
77-
* */
78-
op: string,
71+
* the search string
72+
* */
73+
val: string
74+
/**
75+
* must be one of [ '+', '?', '-' ] corresponding to `ANDS`, `ORS`, and
76+
* `NOTS`, respectively.
77+
* */
78+
op: string
7979
}
8080

8181
/**
82-
* passed to AQL `FILTER`
83-
* */
82+
* passed to AQL `FILTER`
83+
* */
8484
export interface filter {
8585
/** the arango document field name to filter on */
86-
field: string,
86+
field: string
8787
/** the high-level operator to filter by */
88-
op: string,
88+
op: string
8989
/** the query string to filter with */
90-
val: string | number | Date,
90+
val: string | number | Date
9191
}

src/parse.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ export function parseQuery(queryString: string): term[] {
66
let matches = queryString.match(queryRgx)
77
if (!matches) return []
88

9-
return matches.map(match => {
9+
return matches.map((match) => {
1010
/* strip op */
1111
let op = '?'
12-
if (/[+?-]/.test(match[ 0 ])) {
13-
op = match[ 0 ]
12+
if (/[+?-]/.test(match[0])) {
13+
op = match[0]
1414
match = match.substring(1)
1515
}
1616

17-
if (match[ 0 ] == '"' || match[ 0 ] == "'") {
17+
if (match[0] == '"' || match[0] == "'") {
1818
return {
1919
type: 'phr',
2020
val: match,

src/search.ts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ export function buildSearch(query: query): any {
88
typeof query.terms == 'string' ? parseQuery(query.terms) : query.terms
99

1010
/* build boolean pieces */
11-
let ANDS = buildOPS(query.collections, query.terms, '+', query.key)
12-
let ORS = buildOPS(query.collections, query.terms, '?', query.key)
13-
let NOTS = buildOPS(query.collections, query.terms, '-', query.key)
11+
let ANDS = buildOps(query.collections, query.terms, '+', query.key)
12+
let ORS = buildOps(query.collections, query.terms, '?', query.key)
13+
let NOTS = buildOps(query.collections, query.terms, '-', query.key)
1414

1515
/* handle combinations */
1616
if (ANDS && ORS) {
@@ -22,7 +22,7 @@ export function buildSearch(query: query): any {
2222
${NOTS.phrases ? aql.literal(' NOT ') : undefined} ${NOTS.phrases}
2323
${NOTS.phrases && NOTS.tokens ? aql.literal(' AND ') : undefined} ${
2424
NOTS.tokens
25-
}`
25+
}`
2626
}
2727

2828
/* if an empty query.terms string or array is passed, SEARCH true, bringing
@@ -37,11 +37,11 @@ export function buildSearch(query: query): any {
3737
SORT TFIDF(doc) DESC`
3838
}
3939

40-
function buildOPS(
40+
function buildOps(
4141
collections: collection[],
4242
terms: term[],
4343
op: string,
44-
key: string = 'text',
44+
key: string[] | string = 'text',
4545
): any {
4646
const opWord: string = op == '+' ? ' AND ' : ' OR '
4747

@@ -56,16 +56,16 @@ function buildOPS(
5656
let tokens = queryTerms.filter((qT: { type: string }) => qT.type === 'tok')
5757
tokens = tokens && buildTokens(tokens, collections, key)
5858

59-
if (!phrases && !tokens) return
59+
/* if (!phrases && !tokens) return */
6060
if (op == '-') return { phrases, tokens }
61-
if (phrases && tokens) return aql.join([ phrases, tokens ], opWord)
61+
if (phrases && tokens) return aql.join([phrases, tokens], opWord)
6262
return tokens || phrases
6363
}
6464

6565
function buildPhrases(
6666
phrases: term[],
6767
collections: collection[],
68-
key: string,
68+
key: string[] | string,
6969
opWord: string,
7070
): any {
7171
if (!phrases.length) return undefined
@@ -79,7 +79,7 @@ function buildPhrases(
7979
function buildPhrase(
8080
phrase: term,
8181
collections: collection[],
82-
key: string,
82+
key: string[] | string,
8383
): any {
8484
const phrases = collections.map((coll) => {
8585
return aql`PHRASE(doc.${key}, ${phrase.val.slice(1, -1)}, ${coll.analyzer})`
@@ -90,7 +90,7 @@ function buildPhrase(
9090
function buildTokens(
9191
tokens: term[],
9292
collections: collection[],
93-
key: string,
93+
key: string[] | string,
9494
): any {
9595
if (!tokens.length) return
9696

@@ -101,16 +101,16 @@ function buildTokens(
101101
}
102102

103103
const mapped = tokens.reduce((a, v) => {
104-
const op = a[ opWordMap[ v.op ] ]
105-
a[ opWordMap[ v.op ] ] = op ? op + ' ' + v.val : v.val
104+
const op = a[opWordMap[v.op]]
105+
a[opWordMap[v.op]] = op ? op + ' ' + v.val : v.val
106106
return a
107107
}, {})
108108

109109
const makeTokenAnalyzers = (
110110
tokens: term[],
111111
op: string,
112112
analyzer: string,
113-
key: string,
113+
key: string[] | string,
114114
) => {
115115
return aql`
116116
ANALYZER(
@@ -122,11 +122,11 @@ function buildTokens(
122122
collections.forEach((coll) => {
123123
remapped.push(
124124
...Object.keys(mapped).map((op) =>
125-
makeTokenAnalyzers(mapped[ op ], op, coll.analyzer, key),
125+
makeTokenAnalyzers(mapped[op], op, coll.analyzer, key),
126126
),
127127
)
128128
})
129129

130130
return aql`MIN_MATCH(${aql.join(remapped, ', ')},
131-
${tokens[ 0 ].op === '-' ? collections.length : 1})`
131+
${tokens[0].op === '-' ? collections.length : 1})`
132132
}

0 commit comments

Comments
 (0)