UNPKG

11 kBMarkdownView Raw
1# enju [![circle-ci](https://circleci.com/gh/kelp404/enju.png?circle-token=55c92edca67c45f7e79d9d9bc6ffce340a462878)](https://circleci.com/gh/kelp404/enju)
2[![npm version](https://badge.fury.io/js/enju.svg)](https://www.npmjs.com/package/enju)
3
4An elasticsearch client on node.js written in CoffeeScript.
5[tina](https://github.com/kelp404/tina) is the Python version.
6
7![tina](_enju.gif)
8
9
10
11## Installation
12```bash
13$ npm install enju --save
14```
15
16
17
18## Config
19enju use [node-config](https://github.com/lorenwest/node-config).
20`/your_project/config/default.cson`
21```cson
22enjuElasticsearchHost: 'http://localhost:9200'
23enjuIndexPrefix: ''
24```
25
26
27
28## Quick start
29### 1. Define models
30```coffee
31enju = require 'enju'
32class UserModel extends enju.Document
33 @_index = 'users' # your index name
34 @_settings =
35 analysis:
36 analyzer:
37 email_url:
38 type: 'custom'
39 tokenizer: 'uax_url_email'
40 @define
41 name: new enju.StringProperty
42 required: yes
43 email: new enju.StringProperty
44 required: yes
45 analyzer: 'email_url'
46 createTime: new enju.DateProperty
47 autoNow: yes
48 dbField: 'create_time'
49class ProductModel extends enju.Document
50 @_index = 'products'
51 @define
52 user: new enju.ReferenceProperty
53 referenceClass: UserModel
54 required: yes
55 title: new enju.StringProperty
56 required: yes
57```
58### 2. Update elasticsearch mapping
59```coffee
60UserModel.updateMapping()
61ProductModel.updateMapping()
62```
63### 3. Insert documents
64```coffee
65user = new UserModel
66 name: 'Kelp'
67 email: 'kelp@phate.org'
68user.save().then (user) ->
69 product = new ProductModel
70 user: user
71 title: 'enju'
72 product.save()
73```
74### 4. Fetch documents
75```coffee
76ProductModel.where('title', '==': 'enju').fetch().then (result) ->
77 console.log JSON.stringify(result.items, null, 4)
78 # [{
79 # "id": "AU-mMiIwtrhIjlPeQBbT",
80 # "version": 1,
81 # "user": {
82 # "id": "AU-mMiIOtrhIjlPeQBbS",
83 # "version": 1,
84 # "name": "Kelp",
85 # "email": "kelp@phate.org",
86 # "createTime": "2015-09-07T05:05:47.500Z"
87 # },
88 # "title": "enju"
89 # }]
90```
91
92
93
94## Develop
95```bash
96# install dependencies
97npm install -g nodeunit
98npm install -g grunt-cli
99npm install
100```
101
102```bash
103# compile and watch
104grunt dev
105```
106
107```bash
108# build coffee-script
109grunt build
110```
111
112```bash
113# run test
114grunt build
115npm test
116```
117
118
119
120## Document
121```coffee
122# CoffeeScript
123enju = require 'enju'
124class UserModel extends enju.Document
125 @_index = 'users' # your index name
126 @_settings =
127 analysis:
128 analyzer:
129 email_url:
130 type: 'custom'
131 tokenizer: 'uax_url_email'
132 @define
133 name: new enju.StringProperty
134 required: yes
135 email: new enju.StringProperty
136 required: yes
137 analyzer: 'email_url'
138 createTime: new enju.DateProperty
139 autoNow: yes
140 dbField: 'create_time'
141```
142```js
143// JavaScript
144var enju = require('enju');
145var UserModel = enju.Document.define('UserModel', {
146 _index: 'users',
147 _settings: {
148 analysis: {
149 analyzer: {
150 email_url: {
151 type: 'custom',
152 tokenizer: 'uax_url_email'
153 }
154 }
155 }
156 },
157 name: new enju.StringProperty({
158 required: true
159 }),
160 email: new enju.StringProperty({
161 required: true,
162 analyzer: 'email_url'
163 }),
164 createTime: new enju.DateProperty({
165 autoNow: true,
166 dbField: 'create_time'
167 })
168});
169```
170
171**Properties**
172```coffee
173class Document
174 ###
175 _index {string} You can set index name by this attribute. **constructor property**
176 _type {string} You can set type of the document. The default is class name. **constructor property**
177 _settings {object} You can set index settings by this attribute. **constructor property**
178 id {string}
179 version {number}
180 ###
181```
182
183**Class method**
184```coffee
185@get = (ids, fetchReference=yes) ->
186 ###
187 Fetch the document with id or ids.
188 If the document is not exist, it will return null.
189 @param ids {string|list}
190 @param fetchReference {bool} Fetch reference data of this document.
191 @returns {promise<Document>}
192 ###
193# ex: Document.get('MQ-ULRSJ291RG_eEwSfQ').then (result) ->
194# ex: Document.get(['MQ-ULRSJ291RG_eEwSfQ']).then (result) ->
195```
196```coffee
197@exists = (id) ->
198 ###
199 Is the document exists?
200 @param id {string} The documents' id.
201 @returns {promise<bool>}
202 ###
203```
204```coffee
205@all = ->
206 ###
207 Generate a query for this document.
208 @returns {Query}
209 ###
210# ex: query = Document.all()
211```
212```coffee
213@where = (field, operation) ->
214 ###
215 Generate the query for this document.
216 @param field {Property|string|function}
217 Property: The property of the document.
218 string: The property name of the document.
219 function: The sub query.
220 @param operation {object}
221 key: [
222 '!=', 'unequal'
223 '==', 'equal'
224 '<', 'less'
225 '<=', 'lessEqual'
226 '>', 'greater',
227 '>=', 'greaterEqual'
228 'like'
229 'unlike'
230 'contains'
231 'exclude'
232 ]
233 @returns {Query}
234 ###
235# ex: query = Document.where('field', '==': 'value')
236```
237```coffee
238@updateMapping = ->
239 ###
240 Update the index mapping.
241 https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-update-settings.html
242 https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-put-mapping.html
243 @returns {promise}
244 ###
245```
246
247**Method**
248```coffee
249save: (refresh=no) ->
250 ###
251 Save this document.
252 @param refresh {bool} Refresh the index after performing the operation.
253 @returns {promise<Document>}
254 ###
255```
256```coffee
257delete: (refresh=no) ->
258 ###
259 Delete this document.
260 @returns {promise<Document>}
261 ###
262```
263
264
265
266## Property
267```coffee
268class Property
269 ###
270 @property default {bool}
271 @property required {bool}
272 @property dbField {string}
273 @property type {string} For elasticsearch mapping
274 @property index {string} For elasticsearch mapping
275 @property analyzer {string} For elasticsearch mapping
276 @property mapping {object} For elasticsearch mapping
277 @property propertyName {string} The property name in the document. It will be set at Document.define()
278 ###
279```
280```coffee
281class StringProperty extends Property
282```
283```coffee
284class IntegerProperty extends Property
285```
286```coffee
287class FloatProperty extends Property
288```
289```coffee
290class BooleanProperty extends Property
291```
292```coffee
293class DateProperty extends Property
294 ###
295 @property autoNow {bool}
296 ###
297```
298```coffee
299class ListProperty extends Property
300 ###
301 @property itemClass {constructor}
302 ###
303```
304```coffee
305class ObjectProperty extends Property
306```
307```coffee
308class ReferenceProperty extends Property
309 ###
310 @property referenceClass {Property}
311 ###
312```
313
314
315
316## Query
317The enju query.
318
319**Methods**
320```coffee
321where: (field, operation) ->
322 ###
323 Append a query as intersect.
324 @param field {Property|string|function}
325 Property: The property of the document.
326 string: The property name of the document.
327 function: The sub query.
328 @param operation {object}
329 key: [
330 '!=', 'unequal'
331 '==', 'equal'
332 '<', 'less'
333 '<=', 'lessEqual'
334 '>', 'greater',
335 '>=', 'greaterEqual'
336 'like'
337 'unlike'
338 'contains'
339 'exclude'
340 ]
341 @returns {Query}
342 ###
343```
344```coffee
345union: (field, operation) ->
346 ###
347 Append a query as intersect.
348 @param field {Property|string}
349 Property: The property of the document.
350 string: The property name of the document.
351 @param operation {object}
352 key: [
353 '!=', 'unequal'
354 '==', 'equal'
355 '<', 'less'
356 '<=', 'lessEqual'
357 '>', 'greater',
358 '>=', 'greaterEqual'
359 'like'
360 'unlike'
361 'contains'
362 'exclude'
363 ]
364 @returns {Query}
365 ###
366```
367```coffee
368orderBy: (field, descending=no) ->
369 ###
370 Append the order query.
371 @param field {Property|string} The property name of the document.
372 @param descending {bool} Is sorted by descending?
373 @returns {Query}
374 ###
375```
376```coffee
377fetch: (args={}) ->
378 ###
379 Fetch documents by this query.
380 @param args {object}
381 limit: {number} The size of the pagination. (The limit of the result items.) default is 1000
382 skip: {number} The offset of the pagination. (Skip x items.) default is 0
383 fetchReference: {bool} Fetch documents of reference properties. default is true.
384 @returns {promise<object>} ({items: {Document}, total: {number}})
385 ###
386```
387```coffee
388first: (fetchReference=yes) ->
389 ###
390 Fetch the first document by this query.
391 @param fetchReference {bool}
392 @returns {promise<Document|null>}
393 ###
394```
395```
396hasAny: ->
397 ###
398 Are there any documents match with the query?
399 @returns {promise<bool>}
400 ###
401```
402```coffee
403count: ->
404 ###
405 Count documents by the query.
406 @returns {promise<number>}
407 ###
408```
409```coffee
410sum: (field) ->
411 ###
412 Sum the field of documents by the query.
413 https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-sum-aggregation.html
414 @param field {Property|string} The property name of the document.
415 @returns {promise<number>}
416 ###
417```
418
419
420
421## Example
422```sql
423select * from "ExampleModel" where "name" = "tina"
424```
425```coffee
426ExampleModel.where('name', equal: 'tina').fetch().then (result) ->
427```
428
429---
430```sql
431select * from "ExampleModel" where "name" = "tina" and "email" = "kelp@phate.org"
432```
433```coffee
434ExampleModel.where('name', equal: 'enju')
435 .where('email', equal: 'kelp@phate.org')
436 .fetch().then (result) ->
437```
438
439---
440```sql
441select * from "ExampleModel" where "name" like "%tina%" or "email" like "%tina%"
442```
443```coffee
444ExampleModel.where (query) ->
445 query.where('name', like: 'tina').union('email', like: 'tina')
446.fetch().then (result) ->
447```
448
449---
450```sql
451select * from "ExampleModel" where "category" = 1 or "category" = 3
452 order by "created_at" limit 20 offset 20
453```
454```coffee
455ExampleModel.where('category', contains: [1, 3])
456 .orderBy('created_at')
457 .fetch(20, 20).then (result) ->
458```
459
460---
461Fetch the first item.
462```sql
463select * from "ExampleModel" where "age" >= 10
464 order by "created_at" desc limit 1
465```
466```coffee
467ExampleModel.where('age', '>=': 10)
468 .orderBy('created_at', yes).first().then (model) ->
469```
470
471---
472Count items.
473```sql
474select count(*) from "ExampleModel" where "age" < 10
475```
476```python
477ExampleModel.where('age', less: 10).count().then (result) ->
478```
479