Skip to content

Commit 8c4aecf

Browse files
authored
Merge pull request #1 from HP4k1h5/v0.0.1
V0.0.1
2 parents 15c172a + be70fae commit 8c4aecf

19 files changed

+853
-23
lines changed

.github/CONTRIBUTING.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# contributing
2+
[toc]
3+
4+
thanks for using AQLqueryBuilder.js. all contributions are welcome. whether or
5+
not you are considering [contributing code](#code-contributions), please file
6+
an issue. templates are not required.
7+
8+
please try to be respectful of other members of the community and yourself.
9+
10+
## Templates
11+
12+
### features
13+
14+
please file a [feature
15+
request](https://github.com/HP4k1h5/AQLqueryBuilder.js/issues/new?assignees=&labels=&template=feature_request.md&title=)
16+
17+
### bugs
18+
19+
im sorry. please file a [bug report](https://github.com/HP4k1h5/AQLqueryBuilder/issues/new?assignees=HP4k1h5&labels=bug&template=bug_report.md&title=basic)
20+
21+
## code contributions
22+
23+
When contributing code, please:
24+
1) file an issue and describe the bugfix or feature
25+
2) fork this repository
26+
3) checkout the latest version branch, which will be in the `v.X.X.X` format,
27+
and should be the only version branch available. Don't hesitate to ask if it
28+
is unclear.
29+
4) make changes
30+
5) add tests; currently using mochai/chai
31+
run tests with e.g. `yarn test tests/glob`
32+
6) add comments to your functions, and if possible, in the
33+
[typedoc](https://github.com/TypeStrong/typedoc) style
34+
7) submit a merge request from your forked branch into the
35+
latest HP4k1h5/ephemeris `v.X.X.X` branch.

.github/ISSUE_TEMPLATE/bug_report.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
name: Bug report
3+
about: Create a report to help us improve
4+
title: basic
5+
labels: bug
6+
assignees: HP4k1h5
7+
8+
---
9+
10+
**Describe the bug**
11+
A clear and concise description of what the bug is.
12+
13+
**To Reproduce**
14+
Steps to reproduce the behavior:
15+
16+
**Expected behavior**
17+
A clear and concise description of what you expected to happen.
18+
19+
**Screenshots**
20+
If applicable, add screenshots to help explain your problem.
21+
22+
**Desktop (please complete the following information):**
23+
- OS: [e.g. iOS]
24+
- Browser [e.g. chrome, safari]
25+
- Version [e.g. 22]
26+
27+
**Smartphone (please complete the following information):**
28+
- Device: [e.g. iPhone6]
29+
- OS: [e.g. iOS8.1]
30+
- Browser [e.g. stock browser, safari]
31+
- Version [e.g. 22]
32+
33+
**Additional context**
34+
Add any other context about the problem here.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
name: Feature request
3+
about: Suggest an idea for this project
4+
title: ''
5+
labels: ''
6+
assignees: ''
7+
8+
---
9+
10+
**Is your feature request related to a problem? Please describe.**
11+
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12+
13+
**Describe the solution you'd like**
14+
A clear and concise description of what you want to happen.
15+
16+
**Describe alternatives you've considered**
17+
A clear and concise description of any alternative solutions or features you've considered.
18+
19+
**Additional context**
20+
Add any other context or screenshots about the feature request here.

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
built/
22
node_modules/
3+
yarn.lock
4+
docs/
5+
**/*.wiki

README.md

Lines changed: 207 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,208 @@
11
# AQLqueryBuilder.js
2-
a typescript query builder for [arangodb](https://www.arangodb.com)'s [ArangoSearch](https://www.arangodb.com/docs/stable/arangosearch.html)
2+
> a typescript query builder for [arangodb](https://www.arangodb.com)'s [ArangoSearch](https://www.arangodb.com/docs/stable/arangosearch.html)
3+
4+
##### !! warning !! experimental and unstable
5+
6+
## overview
7+
ArangoSearch provides a high-level API for interacting with Arango Search Views
8+
through the Arango Query Language (AQL). This library aims to provide a query
9+
parser and AQL query builder to enable full boolean search operations across
10+
all available Arango Search View capabilities, including, `PHRASE` and
11+
`TOKENS` operations. With minimal syntax overhead the user can generate
12+
multi-lingual and language-specific, complex phrase, proximity and tokenized
13+
search terms.
14+
15+
For example, passing a search phrase like: `+mandatory -exclude ?"optional
16+
phrase"` to `buildAQL`, will produce the following query:
17+
```aql
18+
FOR doc IN search_view
19+
20+
SEARCH
21+
MIN_MATCH(
22+
ANALYZER(
23+
TOKENS(@value0, @value1)
24+
ALL IN doc.@value2, @value1),
25+
@value3) OR (MIN_MATCH(
26+
ANALYZER(
27+
TOKENS(@value0, @value1)
28+
ALL IN doc.@value2, @value1),
29+
@value3) AND @value4)
30+
31+
AND
32+
33+
MIN_MATCH(
34+
ANALYZER(
35+
TOKENS(@value5, @value1)
36+
NONE IN doc.@value2, @value1),
37+
@value3)
38+
39+
OPTIONS @value6
40+
SORT TFIDF(doc) DESC
41+
42+
LIMIT @value7, @value8
43+
RETURN doc
44+
```
45+
This query will retrieve all documents that __include__ the term "mandatory"
46+
AND __do not include__ the term "exclude", AND whose ranking will be boosted by the
47+
presence of the phrase "optional phrase". If no mandatory or exclude terms are
48+
provided, optional terms are considered required, so as not to retrieve all
49+
documents.
50+
51+
## setup
52+
53+
1) running generated AQL queries will require a working arangodb instance. in
54+
the future, it is hoped that this package can be imported and used in the
55+
`arangosh`, as well as client and server side. Currently there is only limited
56+
support for server-side use.
57+
58+
## installation
59+
60+
!! packaging and export behavior is not stable, and is likely to change
61+
!! significantly in the short-term
62+
1) clone this repository in your es6 compatible project.
63+
2) run `yarn install` from the project directory.
64+
65+
## usage
66+
for better documentation, run `yarn doc && serve docs/` from the project
67+
directory root.
68+
69+
AQLqueryBuilder aims to provide collection-agnostic and language-agnostic
70+
boolean search capabilities to the library's user. Currently, this library
71+
makes a number of assumptions about the way your data is stored and indexed,
72+
but these are hopefully compatible with a wide range of setups.
73+
74+
The primary assumption this library makes is that the data you are trying to
75+
query against is indexed by an ArangoSearch View, and that all documents index
76+
the same exact field. This field can be indexed by any number of analyzers,
77+
and the search be will run against all supplied collections simultaneously. This
78+
allows for true multi-language search provided that each collection is
79+
restricted to just one language and all documents index the same key as all
80+
other documents in the view. While there are plans to expand on this
81+
functionality to provide multi-key search, this library is primarily built for
82+
academic and textual searches, and is ideally suited for documents like books,
83+
articles, and other media where most of the data resides in a single place.
84+
85+
This works best as a document query tool. Leveraging ArangoSearch's built-in
86+
language stemming analyzers allows for complex search phrases to be run
87+
against any number of language-specific collections simultaneously.
88+
89+
For an example of a multi-lingual document ingest/parser, please see
90+
[ptolemy's curator](https://gitlab.com/HP4k1h5/nineveh/-/tree/master/ptolemy/dimitri/curator.js)
91+
92+
__Example:__
93+
```javascript
94+
import {buildAQL} from 'path/to/AQLqueryBuilder'
95+
const queryObject =
96+
{
97+
"view": "the_arango-search_view-name",
98+
"collections": [{
99+
"name": "collection_name",
100+
"analyzer": "analyzer_name"
101+
}],
102+
"query": "+'query string' -for +parseQuery ?to parse"
103+
}
104+
const aqlQuery = buildAQL(queryObject)
105+
// ... const cursor = await db.query(aqlQuery)
106+
```
107+
`collections` is an array of `collection` objects. This allows searching and
108+
filtering across collections impacted by the search.
109+
110+
### query object
111+
112+
`buildAQL` accepts an object with the following properties:
113+
114+
**view**: *string* (required): the name of the ArangoSearch view the query
115+
will be run against
116+
117+
**collections** (required): the names of the collections indexed by @view to query
118+
119+
**terms** (required): either an array of @term interfaces or a string to be
120+
parsed by @parseQuery
121+
122+
**key** (optional | default: "text"): the name of the Arango document key to search
123+
within.
124+
125+
**filters** (optional): a list of @filter interfaces
126+
127+
___
128+
129+
Example:
130+
```json
131+
{
132+
"view": "the_arango-search_view-name",
133+
"collections": [
134+
{
135+
"name":
136+
"collection_name", "analyzer":
137+
"analyzer_name"
138+
}
139+
],
140+
"key": "text",
141+
"query": "either a +query ?\"string for parseQuery to parse\"",
142+
"query": [
143+
{"type": "phr", "op": "?", "val": "\"or a list of query objects\""},
144+
{"type": "tok", "op": "-", "val": "tokens"}
145+
],
146+
"filters": [
147+
{
148+
"field": "field_name",
149+
"op": ">",
150+
"val": 0
151+
}
152+
],
153+
"limit":
154+
{
155+
"start": 0,
156+
"end": 20,
157+
}
158+
}
159+
```
160+
161+
### boolean search logic
162+
Quoting [mit's Database Search Tips](https://libguides.mit.edu/c.php?g=175963&p=1158594):
163+
> Boolean operators form the basis of mathematical sets and database logic.
164+
They connect your search words together to either narrow or broaden your
165+
set of results. The three basic boolean operators are: AND, OR, and NOT.
166+
167+
#### `+` AND
168+
* Mandatory terms and phrases. All results MUST INCLUDE these terms and
169+
* phrases.
170+
#### `?` OR
171+
* Optional terms and phrases. If there are ANDS or NOTS, these serve as
172+
* match score "boosters". If there are no ANDS or NOTS, ORS become required
173+
* in results.
174+
#### `-` NOT
175+
* Search results MUST NOT INCLUDE these terms and phrases. If a result that
176+
* would otherwise have matched, contains one or more terms or phrases, it
177+
* will not be included in the result set.
178+
179+
### default query syntax
180+
for more information on boolean search logic see
181+
[above](#boolean-search-logic)
182+
183+
The default syntax accepted by `AQLqueryBuilder`'s `query` object's `terms`
184+
key is as follows:
185+
186+
1) Everything inside single or double quotes is considered a `PHRASE`
187+
2) Everything else is considered a word to be analyzed by `TOKENS`
188+
3) Every individual search word and quoted phrase may be optionally prefixed
189+
by one of the following symbols `+ ? -`, or the plus-sign, the question-mark,
190+
and the minus-sign. If a word has no operator prefix, it is considered
191+
optional and is counted as an `OR`.
192+
193+
Example:
194+
input `one +two -"buckle my shoe"` and the queryParser will interpret as
195+
follows:
196+
197+
| | ANDS | ORS | NOTS |
198+
| - | - | - | - |
199+
| PHRASE | | | "buckle my shoe" |
200+
| TOKENS | two | one | |
201+
202+
The generated AQL query, when run will bring back only results that contain
203+
"two", that do not contain variations on the phrase "buckle my shoe", and that
204+
optionally contain "one". In this case, documents that contain "one" will be
205+
likely to score higher than those that do not.
206+
207+
## bugs
208+
## contributing

package.json

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,43 @@
11
{
2-
"name": "aql-js-andsorsnots",
3-
"version": "0.0.0",
2+
"name": "@hp4k1h5/aqlquerybuilder.js",
3+
"version": "0.0.1",
44
"license": "MIT",
5+
"main": "./built/index.d.ts",
6+
"scripts": {
7+
"test": "mocha -r ts-node/register",
8+
"tests": "mocha -r ts-node/register 'tests/*.ts'",
9+
"doc": "typedoc --plugin none src/"
10+
},
11+
"homepage": "https://github.com/HP4k1h5/AQLqueryBuilder.js",
12+
"repository": {
13+
"type": "git",
14+
"url": "git@github.com:HP4k1h5/AQLqueryBuilder.js.git"
15+
},
16+
"description": "a typescript query builder for the Arango Query Language (AQL) via ArangoSearch",
17+
"keywords": [
18+
"AQL",
19+
"arangojs",
20+
"arangodb",
21+
"ArangoSearch",
22+
"nodeJs",
23+
"query-builder",
24+
"query-parser",
25+
"typescript"
26+
],
27+
"dependencies": {
28+
"arangojs": "^6.14.1"
29+
},
530
"devDependencies": {
31+
"@types/chai": "^4.2.11",
32+
"@types/mocha": "^7.0.2",
33+
"@types/node": "^14.0.13",
34+
"chai": "^4.2.0",
35+
"mocha": "^8.0.1",
36+
"ts-node": "^8.10.2",
37+
"typedoc": "^0.17.7",
38+
"typedoc-plugin-markdown": "^2.3.1",
639
"typescript": "^3.9.5"
7-
}
40+
},
41+
"author": "HP4k1h5",
42+
"email": "robertwalks@gmail.com"
843
}

src/collections.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/filter.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { aql } from 'arangojs'
2+
import { filter } from './lib/structs'
3+
4+
export function buildFilters(filters: filter[]) {
5+
if (!filters.length) return
6+
7+
let _filters = filters.map(
8+
(f: filter) => aql`doc.${f.field} ${aql.literal(f.op)} ${f.val}`,
9+
)
10+
11+
return aql`FILTER ${aql.join(_filters, ' && ')}`
12+
}

0 commit comments

Comments
 (0)