{"id":13783234,"url":"https://github.com/kelp404/enju","last_synced_at":"2025-04-13T06:31:17.676Z","repository":{"id":57225505,"uuid":"41630607","full_name":"kelp404/enju","owner":"kelp404","description":"An Elasticsearch client on Node.js written in CoffeeScript.","archived":false,"fork":false,"pushed_at":"2023-01-02T03:24:23.000Z","size":1386,"stargazers_count":13,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-11T15:27:43.430Z","etag":null,"topics":["coffeescript","elasticsearch","elasticsearch-client","nodejs","orm"],"latest_commit_sha":null,"homepage":"","language":"CoffeeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kelp404.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-08-30T14:00:51.000Z","updated_at":"2023-09-05T17:19:52.000Z","dependencies_parsed_at":"2023-02-01T01:45:55.958Z","dependency_job_id":null,"html_url":"https://github.com/kelp404/enju","commit_stats":null,"previous_names":[],"tags_count":46,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kelp404%2Fenju","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kelp404%2Fenju/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kelp404%2Fenju/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kelp404%2Fenju/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kelp404","download_url":"https://codeload.github.com/kelp404/enju/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248637297,"owners_count":21137531,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["coffeescript","elasticsearch","elasticsearch-client","nodejs","orm"],"created_at":"2024-08-03T19:00:16.816Z","updated_at":"2025-04-13T06:31:17.552Z","avatar_url":"https://github.com/kelp404.png","language":"CoffeeScript","funding_links":[],"categories":["Elasticsearch developer tools and utilities"],"sub_categories":["Development and debugging"],"readme":"# enju\n[![npm version](https://badge.fury.io/js/enju.svg)](https://www.npmjs.com/package/enju)\n[![Coverage Status](https://coveralls.io/repos/github/kelp404/enju/badge.svg)](https://coveralls.io/github/kelp404/enju)\n  \n\nAn elasticsearch client on node.js written in CoffeeScript.  \nEnju provides a simple way to define mapping and access data.\n\n\n  enju  |  Elasticsearch\n:-----:|:-------------:\n   2.x   |        2.4\n   5.x   |        5.6\n\n![tina](_enju.gif)\n\n\n\n## Installation\n```bash\n$ npm install enju --save\n```\n\n\n\n## Config\nenju use [node-config](https://github.com/lorenwest/node-config).  \n`/your_project/config/default.json`  \nRead more elasticsearch config at here:  \n[https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/configuration.html](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/configuration.html)\n```json\n{\n    \"enju\": {\n        \"indexPrefix\": \"\",\n        \"elasticsearchConfig\": {\n            \"apiVersion\": \"5.6\",\n            \"host\": \"http://localhost:9200\"\n        }\n    }\n}\n```\n\n\n\n## Quick start\n### 1. Define models\n```coffee\nenju = require 'enju'\nclass UserModel extends enju.Document\n    @_index = 'users'  # your index name\n    @_settings =\n        analysis:\n            analyzer:\n                email_url:\n                    type: 'custom'\n                    tokenizer: 'uax_url_email'\n    @define\n        name: new enju.KeywordProperty\n            required: yes\n        email: new enju.TextProperty\n            required: yes\n            analyzer: 'email_url'\n        createTime: new enju.DateProperty\n            autoNow: yes\n            dbField: 'create_time'\nclass ProductModel extends enju.Document\n    @_index = 'products'\n    @define\n        user: new enju.ReferenceProperty\n            referenceClass: UserModel\n            required: yes\n        title: new enju.KeywordProperty\n            required: yes\n```\n### 2. Update elasticsearch mapping\n```coffee\nUserModel.updateMapping()\nProductModel.updateMapping()\n```\n### 3. Insert documents\n```coffee\nuser = new UserModel\n    name: 'Kelp'\n    email: 'kelp@phate.org'\nuser.save().then (user) -\u003e\n    product = new ProductModel\n        user: user\n        title: 'enju'\n    product.save()\n```\n### 4. Fetch documents\n```coffee\nProductModel.where('title', '==': 'enju').fetch().then (result) -\u003e\n    console.log JSON.stringify(result.items, null, 4)\n    # [{\n    #     \"id\": \"AU-mMiIwtrhIjlPeQBbT\",\n    #     \"version\": 1,\n    #     \"user\": {\n    #         \"id\": \"AU-mMiIOtrhIjlPeQBbS\",\n    #         \"version\": 1,\n    #         \"name\": \"Kelp\",\n    #         \"email\": \"kelp@phate.org\",\n    #         \"createTime\": \"2015-09-07T05:05:47.500Z\"\n    #     },\n    #     \"title\": \"enju\"\n    # }]\n```\n\n\n\n## Develop\n```bash\n# install dependencies\nnpm install -g grunt-cli\nnpm install\n```\n\n```bash\n# compile and watch\ngrunt dev\n```\n\n```bash\n# build CoffeeScript\nnpm run build\n```\n\n```bash\n# run test\nnpm run build\nnpm test\n```\n\n\n\n## Document\n```coffee\n# CoffeeScript\nenju = require 'enju'\nclass UserModel extends enju.Document\n    @_index = 'users'  # your index name\n    @_settings =\n        analysis:\n            analyzer:\n                email_url:\n                    type: 'custom'\n                    tokenizer: 'uax_url_email'\n    @define\n        name: new enju.KeywordProperty\n            required: yes\n        email: new enju.TextProperty\n            required: yes\n            analyzer: 'email_url'\n        createTime: new enju.DateProperty\n            autoNow: yes\n            dbField: 'create_time'\n```\n```js\n// JavaScript\nvar enju = require('enju');\nvar UserModel = enju.Document.define('UserModel', {\n    _index: 'users',\n    _settings: {\n        analysis: {\n            analyzer: {\n                email_url: {\n                    type: 'custom',\n                    tokenizer: 'uax_url_email'\n                }\n            }\n        }\n    },\n    name: new enju.KeywordProperty({\n        required: true\n    }),\n    email: new enju.TextProperty({\n        required: true,\n        analyzer: 'email_url'\n    }),\n    createTime: new enju.DateProperty({\n        autoNow: true,\n        dbField: 'create_time'\n    })\n});\n```\n\n**Properties**\n```coffee\nclass Document\n    ###\n    _index {string} You can set index name by this attribute. **constructor property**\n    _type {string} You can set type of the document. The default is class name. **constructor property**\n    _settings {object} You can set index settings by this attribute. **constructor property**\n    id {string}\n    version {number}\n    ###\n```\n\n**Class method**\n```coffee\n@get = (ids, fetchReference=yes) -\u003e\n    ###\n    Fetch the document with id or ids.\n    If the document is not exist, it will return null.\n    @param ids {string|list}\n    @param fetchReference {bool} Fetch reference data of this document.\n    @returns {promise\u003cDocument\u003e}\n    ###\n# ex: Document.get('MQ-ULRSJ291RG_eEwSfQ').then (result) -\u003e\n# ex: Document.get(['MQ-ULRSJ291RG_eEwSfQ']).then (result) -\u003e\n```\n```coffee\n@exists = (id) -\u003e\n    ###\n    Is the document exists?\n    @param id {string} The documents' id.\n    @returns {promise\u003cbool\u003e}\n    ###\n```\n```coffee\n@all = -\u003e\n    ###\n    Generate a query for this document.\n    @returns {Query}\n    ###\n# ex: query = Document.all()\n```\n```coffee\n@where = (field, operation) -\u003e\n    ###\n    Generate the query for this document.\n    @param field {string|function}\n        string: The property name of the document.\n        function: The sub query.\n    @param operation {object}\n        key: [\n            '!=', 'unequal'\n            '==', 'equal'\n            '\u003c', 'less'\n            '\u003c=', 'lessEqual'\n            '\u003e', 'greater',\n            '\u003e=', 'greaterEqual'\n            'like'\n            'unlike'\n            'contains'\n            'exclude'\n        ]\n    @returns {Query}\n    ###\n# ex: query = Document.where('field', '==': 'value')\n```\n```coffee\n@refresh = (args) -\u003e\n    ###\n    Explicitly refresh one or more index.\n    https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/api-reference-5-6.html#api-indices-refresh-5-6\n    @params args {object}\n    @returns {promise}\n    ###\n```\n```coffee\n@updateMapping = -\u003e\n    ###\n    Update the index mapping.\n    https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-update-settings.html\n    https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-put-mapping.html\n    @returns {promise}\n    ###\n```\n\n**Method**\n```coffee\nsave: (refresh=no) -\u003e\n    ###\n    Save this document.\n    @param refresh {bool} Refresh the index after performing the operation.\n    @returns {promise\u003cDocument\u003e}\n    ###\n```\n```coffee\ndelete: (refresh=no) -\u003e\n    ###\n    Delete this document.\n    @returns {promise\u003cDocument\u003e}\n    ###\n```\n\n\n\n## Property\n```coffee\nclass Property\n    ###\n    @property default {any}\n    @property required {bool}\n    @property dbField {string}\n    @property type {string}  https://www.elastic.co/guide/en/elasticsearch/reference/5.6/mapping-types.html\n    @property index {bool}  https://www.elastic.co/guide/en/elasticsearch/reference/5.6/mapping-index.html\n    @property mapping {object}  https://www.elastic.co/guide/en/elasticsearch/reference/5.6/mapping.html\n    @property propertyName {string} The property name in the document. It will be set at Document.define()\n    ###\n```\n```coffee\nclass StringProperty extends Property\n    ###\n    https://www.elastic.co/guide/en/elasticsearch/reference/5.6/analyzer.html\n    @property analyzer {string}\n    ###\n```\n```coffee\nclass TextProperty extends Property\n    ###\n    https://www.elastic.co/guide/en/elasticsearch/reference/5.6/analyzer.html\n    @property analyzer {string}\n    ###\n```\n```coffee\nclass KeywordProperty extends Property\n    ###\n    https://www.elastic.co/guide/en/elasticsearch/reference/5.6/analysis-normalizers.html\n    @property normalizer {string}\n    ###\n```\n```coffee\nclass IntegerProperty extends Property\n```\n```coffee\nclass FloatProperty extends Property\n```\n```coffee\nclass BooleanProperty extends Property\n```\n```coffee\nclass DateProperty extends Property\n    ###\n    @property autoNow {bool}\n    ###\n```\n```coffee\nclass ListProperty extends Property\n    ###\n    @property itemClass {constructor}\n    ###\n```\n```coffee\nclass ObjectProperty extends Property\n```\n```coffee\nclass ReferenceProperty extends Property\n    ###\n    @property referenceClass {Property}\n    ###\n```\n\n\n\n## Query\nThe enju query.\n\n**Methods**\n```coffee\nwhere: (field, operation) -\u003e\n    ###\n    Append a query as intersect.\n    @param field {string|function}\n        string: The property name of the document.\n        function: The sub query.\n    @param operation {object}\n        key: [\n            '!=', 'unequal'\n            '==', 'equal'\n            '\u003c', 'less'\n            '\u003c=', 'lessEqual'\n            '\u003e', 'greater',\n            '\u003e=', 'greaterEqual'\n            'like'\n            'unlike'\n            'contains'\n            'exclude'\n        ]\n    @returns {Query}\n    ###\n```\n```coffee\nunion: (field, operation) -\u003e\n    ###\n    Append a query as intersect.\n    @param field {string} string: The property name of the document.\n    @param operation {object}\n        key: [\n            '!=', 'unequal'\n            '==', 'equal'\n            '\u003c', 'less'\n            '\u003c=', 'lessEqual'\n            '\u003e', 'greater',\n            '\u003e=', 'greaterEqual'\n            'like'\n            'unlike'\n            'contains'\n            'exclude'\n        ]\n    @returns {Query}\n    ###\n```\n```coffee\norderBy: (field, descending=no) -\u003e\n    ###\n    Append the order query.\n    @param field {string} The property name of the document.\n    @param descending {bool} Is sorted by descending?\n    @returns {Query}\n    ###\n```\n```coffee\nfetch: (args={}) -\u003e\n    ###\n    Fetch documents by this query.\n    @param args {object}\n        limit: {number} The size of the pagination. (The limit of the result items.) default is 1000\n        skip: {number} The offset of the pagination. (Skip x items.) default is 0\n        fetchReference: {bool} Fetch documents of reference properties. default is true.\n    @returns {promise\u003cobject\u003e} ({items: {Document}, total: {number}})\n    ###\n```\n```coffee\nfirst: (fetchReference=yes) -\u003e\n    ###\n    Fetch the first document by this query.\n    @param fetchReference {bool}\n    @returns {promise\u003cDocument|null\u003e}\n    ###\n```\n```coffee\ncount: -\u003e\n    ###\n    Count documents by the query.\n    @returns {promise\u003cnumber\u003e}\n    ###\n```\n```coffee\nsum: (field) -\u003e\n    ###\n    Sum the field of documents by the query.\n    https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-sum-aggregation.html\n    @param field {string} The property name of the document.\n    @returns {promise\u003cnumber\u003e}\n    ###\n```\n```coffee\ngroupBy: (field, args) -\u003e\n    ###\n    @param field {string} The property name of the document.\n    @param args {object}\n        limit: {number}  Default is 1,000.\n        order: {string} \"count|term\"  Default is \"term\".\n        descending: {bool}  Default is no.\n    @returns {promise\u003clist\u003cobject\u003e\u003e}\n        [{\n            doc_count: {number}\n            key: {string}\n        }]\n    ###\n```\n\n\n\n## Example\n```sql\nselect * from \"ExampleModel\" where \"name\" = \"tina\"\n```\n```coffee\nExampleModel.where('name', equal: 'tina').fetch().then (result) -\u003e\n```\n\n---\n```sql\nselect * from \"ExampleModel\" where \"name\" = \"tina\" and \"email\" = \"kelp@phate.org\"\n```\n```coffee\nExampleModel.where('name', equal: 'enju')\n    .where('email', equal: 'kelp@phate.org')\n    .fetch().then (result) -\u003e\n```\n\n---\n```sql\nselect * from \"ExampleModel\" where \"name\" like \"%tina%\" or \"email\" like \"%tina%\"\n```\n```coffee\nExampleModel.where (query) -\u003e\n    query.where('name', like: 'tina').union('email', like: 'tina')\n.fetch().then (result) -\u003e\n```\n\n---\n```sql\nselect * from \"ExampleModel\" where \"category\" = 1 or \"category\" = 3\n    order by \"created_at\" limit 20 offset 20\n```\n```coffee\nExampleModel.where('category', contains: [1, 3])\n    .orderBy('created_at')\n    .fetch(20, 20).then (result) -\u003e\n```\n\n---\nFetch the first item.\n```sql\nselect * from \"ExampleModel\" where \"age\" \u003e= 10\n     order by \"created_at\" desc limit 1\n```\n```coffee\nExampleModel.where('age', '\u003e=': 10)\n    .orderBy('created_at', yes).first().then (model) -\u003e\n```\n\n---\nCount items.\n```sql\nselect count(*) from \"ExampleModel\" where \"age\" \u003c 10\n```\n```coffee\nExampleModel.where('age', less: 10).count().then (result) -\u003e\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkelp404%2Fenju","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkelp404%2Fenju","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkelp404%2Fenju/lists"}