{"id":13471670,"url":"https://github.com/danpaz/bodybuilder","last_synced_at":"2025-05-14T13:05:47.819Z","repository":{"id":36214962,"uuid":"40519241","full_name":"danpaz/bodybuilder","owner":"danpaz","description":"An elasticsearch query body builder :muscle:","archived":false,"fork":false,"pushed_at":"2023-07-19T15:24:29.000Z","size":3328,"stargazers_count":1249,"open_issues_count":10,"forks_count":127,"subscribers_count":28,"default_branch":"master","last_synced_at":"2025-04-20T21:30:11.968Z","etag":null,"topics":["builder","elasticsearch","hacktoberfest","javascript","querydsl"],"latest_commit_sha":null,"homepage":"http://bodybuilder.js.org","language":"JavaScript","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/danpaz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null},"funding":{"github":["danpaz"]}},"created_at":"2015-08-11T03:27:19.000Z","updated_at":"2025-02-26T13:01:39.000Z","dependencies_parsed_at":"2022-07-29T21:09:43.620Z","dependency_job_id":"417437a6-2727-4c89-a964-e142e12e3888","html_url":"https://github.com/danpaz/bodybuilder","commit_stats":{"total_commits":502,"total_committers":34,"mean_commits":"14.764705882352942","dds":0.4462151394422311,"last_synced_commit":"e3d6b346c44c852c7d2a44d4e56d6d7ff693a679"},"previous_names":[],"tags_count":65,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danpaz%2Fbodybuilder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danpaz%2Fbodybuilder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danpaz%2Fbodybuilder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danpaz%2Fbodybuilder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/danpaz","download_url":"https://codeload.github.com/danpaz/bodybuilder/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254149919,"owners_count":22022851,"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":["builder","elasticsearch","hacktoberfest","javascript","querydsl"],"created_at":"2024-07-31T16:00:48.048Z","updated_at":"2025-05-14T13:05:47.793Z","avatar_url":"https://github.com/danpaz.png","language":"JavaScript","readme":"# bodybuilder\n[![All Contributors](https://img.shields.io/badge/all_contributors-9-orange.svg?style=flat-square)](#contributors)\n[![npm version](https://badge.fury.io/js/bodybuilder.svg)](https://www.npmjs.com/package/bodybuilder)\n[![Build Status](https://travis-ci.org/danpaz/bodybuilder.svg?branch=master)](https://travis-ci.org/danpaz/bodybuilder)\n\nAn elasticsearch query body builder. Easily build complex queries for\nelasticsearch with a simple, predictable api.\n\n![bodybuilder](img/bodybuilder.jpeg)\n\n# Documentation\n\n**Check out the [API documentation](http://bodybuilder.js.org/docs)** for details and examples.\n\nUse https://bodybuilder.js.org/ to test your constructions.\n\n## Elasticsearch compatibility\n\nCurrently aims to support the full elasticsearch query DSL for all versions.\n\nThe elasticsearch 1.x query DSL is supported by providing a `v1` argument\nwhen calling the `build` function.\n\n## Install\n\n    npm install bodybuilder --save\n\n## Usage\n\n```js\nvar bodybuilder = require('bodybuilder')\nvar body = bodybuilder().query('match', 'message', 'this is a test')\nbody.build() // Build 2.x or greater DSL (default)\nbody.build('v1') // Build 1.x DSL\n```\n\nFor each elasticsearch query body, create an instance of `bodybuilder`, apply\nthe desired query/filter/aggregation clauses, and call `build` to retrieve the\nbuilt query body.\n\n## REPL\n\nTry it out on the command line using the node REPL:\n\n    # Start the repl\n    node ./node_modules/bodybuilder/repl.js\n    # The builder is available in the context variable bodybuilder\n    bodybuilder \u003e bodybuilder().query('match', 'message', 'this is a test').build()\n\n### Queries\n\n```js\nbodybuilder().query([arguments])\n```\n\nCreates a query of type `queryType`.\n\n#### Arguments\n\nThe specific arguments depend on the type of query, but typically follow this\npattern:\n\n* `queryType` - The name of the query, such as `'term'` or `'prefix'`.\n* `fieldToQuery` - The name of the field in your index to query over.\n* `searchTerm` - The string to search for.\n\n```js\nvar body = bodybuilder().query('match', 'message', 'this is a test').build()\n// body == {\n//   query: {\n//     match: {\n//       message: 'this is a test'\n//     }\n//   }\n// }\n```\n\n### Filters\n\n```js\nbodybuilder().filter([arguments])\n```\n\nCreates a filtered query using filter of type `filterType`.\n\n#### Arguments\n\nThe specific arguments depend on the type of filter, but typically follow this\npattern:\n\n* `filterType` - The name of the query, such as `'regexp'` or `'exists'`.\n* `fieldToQuery` - The name of the field in your index to filter on.\n* `searchTerm` - The string to search for.\n\n```js\nbodybuilder().filter('term', 'message', 'test').build()\n// body == {\n//   query: {\n//     bool: {\n//       filter: {\n//         term: {\n//           message: 'test'\n//         }\n//       }\n//     }\n//   }\n// }\n```\n\n### Aggregations\n\n```js\nbodybuilder().aggregation([arguments])\n```\n\nCreates an aggregation of type `aggregationType`.\n\n#### Arguments\n\nThe specific arguments depend on the type of aggregation, but typically follow\nthis pattern:\n\n* `aggregationType` - The name of the aggregation, such as `'sum'` or `'terms'`.\n* `fieldToAggregate` - The name of the field in your index to aggregate over.\n* `aggregationName` - (optional) A custom name for the aggregation. Defaults to\n`agg_\u003caggregationType\u003e_\u003cfieldToAggregate\u003e`.\n* `aggregationOptions` - (optional) Additional key-value pairs to include in the\naggregation object.\n* `nestingFunction` - (optional) A function used to define aggregations as\nchildren of the one being created. This _must_ be the last parameter set.\n\n```js\nvar body = bodybuilder().aggregation('terms', 'user').build()\n// body == {\n//   aggregations: {\n//     agg_terms_user: {\n//       terms: {\n//         field: 'user'\n//       }\n//     }\n//   }\n// }\n```\n\n#### Nested aggregations\n\nTo nest aggregations, pass a `function` as the last parameter in `[arguments]`.\nThe `function` receives the recently built aggregation instance and is expected\nto return an `Object` which will be assigned to `.aggs` on the current\naggregation. Aggregations in this scope behave like builders and you can call\nthe chainable method `.aggregation([arguments])` on them just as you would on\nthe main `bodybuilder`.\n\n```js\nvar body = bodybuilder().aggregation('terms', 'code', {\n      order: { _term: 'desc' },\n      size: 1\n    }, agg =\u003e agg.aggregation('terms', 'name')).build()\n// body == {\n//   \"aggregations\": {\n//       \"agg_terms_code\": {\n//           \"terms\": {\n//               \"field\": \"code\",\n//               \"order\": {\n//                   \"_term\": \"desc\"\n//               },\n//               \"size\": 1\n//           },\n//           \"aggs\": {\n//               \"agg_terms_name\": {\n//                   \"terms\": {\n//                       \"field\": \"name\"\n//                   }\n//               }\n//           }\n//       }\n//   }\n//}\n```\n\n### Suggestions\n\n```js\nbodybuilder().suggest([arguments])\n```\n\nCreates a `phrase` or `term` suggestion.\n\n#### Arguments\n\nThe specific arguments depend on the type of aggregation, but typically follow\nthis pattern:\n\n* `suggestionType` - This can be either `phrase` or `term`.\n* `fieldToAggregate` - The name of the field in your index to suggest on.\n* `options` - An object of fields to include in the suggestions.\n  * `text` - The query to run on our suggest field.\n  * `name` - A custom name for the suggest clause.\n  * `analyzer` - The name of an analyzer to run on a suggestion.\n  * ... other suggest specific options, see [typings]('./bodybuilder.d.ts') or the [ElasticSearch suggest docs](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters.html) for more info\n\n\n\n```js\nvar body = bodybuilder().suggest('term', 'user', { text: 'kimchy', 'name': 'user_suggest'}).build()\n// body == {\n//   aggregations: {\n//     user_suggest: {\n//       text: 'kimchy',\n//       term: {\n//         field: 'user'\n//       }\n//     }\n//   }\n// }\n```\n\n### Combining queries, filters, aggregations, and suggestions\n\nMultiple queries and filters are merged using the boolean query or filter (see\n[Combining Filters](https://www.elastic.co/guide/en/elasticsearch/guide/current/combining-filters.html)).\n\n```js\nvar body = bodybuilder()\n  .query('match', 'message', 'this is a test')\n  .filter('term', 'user', 'kimchy')\n  .filter('term', 'user', 'herald')\n  .orFilter('term', 'user', 'johnny')\n  .notFilter('term', 'user', 'cassie')\n  .aggregation('terms', 'user')\n  .suggest('term', 'user', { text: 'kimchy' })\n  .build()\n\n// body == {\n//   query: {\n//     bool: {\n//       must: {\n//         match: {\n//           message: 'this is a test'\n//         }\n//       },\n//       filter: {\n//         bool: {\n//           must: [\n//             {term: {user: 'kimchy'}},\n//             {term: {user: 'herald'}}\n//           ],\n//           should: [\n//             {term: {user: 'johnny'}}\n//           ],\n//           must_not: [\n//             {term: {user: 'cassie'}}\n//           ]\n//         }\n//       }\n//     },\n//   },\n//   aggs: {\n//     agg_terms_user: {\n//       terms: {\n//         field: 'user'\n//       }\n//     }\n//   }\n//   suggest_term_user: {\n//     text: 'kimchy',\n//     term: {\n//       field: 'user'\n//     }\n//   }\n// }\n```\n\n#### Nesting Filters and Queries\n\nIt is even possible to nest filters, e.g. when some should and must filters have to be combined.\n\n```js\nvar body = bodybuilder()\n    .orFilter('term', 'author', 'kimchy')\n    .orFilter('bool', b =\u003e b\n      .filter('match', 'message', 'this is a test')\n      .filter('term', 'type', 'comment')\n    )\n    .build()\n\n// body == {\n//   query: {\n//     bool: {\n//       filter: {\n//         bool: {\n//           should: [\n//             { term: { author: 'kimchy' } },\n//             { bool: { must: [\n//               { match: { message: 'this is a test' } },\n//               { term: { type: 'comment' } }\n//             ] } }\n//           ]\n//         }\n//       }\n//     }\n//   }\n// }\n```\n\n### Sort\n\nSet a sort direction using `sort(field, direction)`, where direction defaults to\nascending.\n\n```js\nvar body = bodybuilder()\n    .filter('term', 'message', 'test')\n    .sort('timestamp', 'desc')\n    .sort([{\n      \"channel\": {\n        \"order\": \"desc\"\n      }\n    }])\n    .sort([\n      {\"categories\": \"desc\"},\n      {\"content\": \"asc\"}\n    ])\n    .build()\n\n// body == {\n//   sort: [{\n//       \"timestamp\": {\n//         \"order\": \"desc\"\n//       }\n//     },\n//     {\n//       \"channel\": {\n//         \"order\": \"desc\"\n//       }\n//     },\n//     {\n//       \"categories\": {\n//         \"order\": \"desc\"\n//       }\n//     },\n//     {\n//       \"content\": {\n//         \"order\": \"asc\"\n//       }\n//     }\n//   ],\n//   query: {\n//     bool: {\n//       filter: {\n//         term: {\n//           message: 'test'\n//         }\n//       }\n//     }\n//   }\n// }\n```\n**Advanced usage:** Set a sort configuration object for the given sort field with additional [sort properties](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-sort.html).\n`sort(field, { sort: 'asc', mode: 'min', ...})`\n\n### From / Size\n\nSet `from` and `size` parameters to configure the offset and maximum hits to be\nreturned.\n\n```js\nvar body = bodybuilder()\n  .filter('term', 'message', 'test')\n  .size(5)\n  .from(10)\n  .build()\n\n// body == {\n//   size: 5,\n//   from: 10,\n//   query: {\n//     bool: {\n//       filter: {\n//         term: {\n//           message: 'test'\n//         }\n//       }\n//     }\n//   }\n// }\n```\n\n### Other Options\n\nSet any other search request option using `rawOption` passing in the key-value\npair to include in the body.\n\n```js\nvar body = bodybuilder()\n  .filter('term', 'message', 'test')\n  .rawOption('_sourceExclude', 'verybigfield')\n  .build()\n\n// body == {\n//   _sourceExclude: 'verybigfield',\n//   query: {\n//     bool: {\n//       filter: {\n//         term: {\n//           message: 'test'\n//         }\n//       }\n//     }\n//   }\n// }\n```\n\n## Test\n\nRun unit tests:\n\n    npm test\n\n## Contributors\n\nThanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds/all-contributors#emoji-key)):\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n| [\u003cimg src=\"https://avatars3.githubusercontent.com/u/5665333?v=4\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eDaniel Paz-Soldan\u003c/sub\u003e](http://danpaz.me/)\u003cbr /\u003e[💻](https://github.com/danpaz/bodybuilder/commits?author=danpaz \"Code\") [📖](https://github.com/danpaz/bodybuilder/commits?author=danpaz \"Documentation\") [🚇](#infra-danpaz \"Infrastructure (Hosting, Build-Tools, etc)\") [🤔](#ideas-danpaz \"Ideas, Planning, \u0026 Feedback\") | [\u003cimg src=\"https://avatars3.githubusercontent.com/u/476069?v=4\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eNicolás Fantone\u003c/sub\u003e](https://github.com/nfantone)\u003cbr /\u003e[💻](https://github.com/danpaz/bodybuilder/commits?author=nfantone \"Code\") [⚠️](https://github.com/danpaz/bodybuilder/commits?author=nfantone \"Tests\") | [\u003cimg src=\"https://avatars0.githubusercontent.com/u/967979?v=4\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eNauval Atmaja\u003c/sub\u003e](http://nauvalatmaja.com)\u003cbr /\u003e[💻](https://github.com/danpaz/bodybuilder/commits?author=npatmaja \"Code\") | [\u003cimg src=\"https://avatars2.githubusercontent.com/u/159764?v=4\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eFerron H\u003c/sub\u003e](https://ferronrsmith.github.io/)\u003cbr /\u003e[💻](https://github.com/danpaz/bodybuilder/commits?author=ferronrsmith \"Code\") [⚠️](https://github.com/danpaz/bodybuilder/commits?author=ferronrsmith \"Tests\") [🐛](https://github.com/danpaz/bodybuilder/issues?q=author%3Aferronrsmith \"Bug reports\") [📖](https://github.com/danpaz/bodybuilder/commits?author=ferronrsmith \"Documentation\") | [\u003cimg src=\"https://avatars3.githubusercontent.com/u/352835?v=4\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eDave Cranwell\u003c/sub\u003e](http://davecranwell.com)\u003cbr /\u003e[💻](https://github.com/danpaz/bodybuilder/commits?author=davecranwell \"Code\") | [\u003cimg src=\"https://avatars0.githubusercontent.com/u/5310458?v=4\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eJohannes Scharlach\u003c/sub\u003e](https://github.com/johannes-scharlach)\u003cbr /\u003e[💻](https://github.com/danpaz/bodybuilder/commits?author=johannes-scharlach \"Code\") [📖](https://github.com/danpaz/bodybuilder/commits?author=johannes-scharlach \"Documentation\") [🤔](#ideas-johannes-scharlach \"Ideas, Planning, \u0026 Feedback\") | [\u003cimg src=\"https://avatars3.githubusercontent.com/u/102233?v=4\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eAnton Samper Rivaya\u003c/sub\u003e](https://rivaya.com)\u003cbr /\u003e[💻](https://github.com/danpaz/bodybuilder/commits?author=antonsamper \"Code\") [📖](https://github.com/danpaz/bodybuilder/commits?author=antonsamper \"Documentation\") |\n| :---: | :---: | :---: | :---: | :---: | :---: | :---: |\n| [\u003cimg src=\"https://avatars2.githubusercontent.com/u/22251956?v=4\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eSuhas Karanth\u003c/sub\u003e](https://github.com/sudo-suhas)\u003cbr /\u003e[💬](#question-sudo-suhas \"Answering Questions\") | [\u003cimg src=\"https://avatars1.githubusercontent.com/u/130874?v=4\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eJacob Gillespie\u003c/sub\u003e](https://github.com/jacobwgillespie)\u003cbr /\u003e[💻](https://github.com/danpaz/bodybuilder/commits?author=jacobwgillespie \"Code\") |\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n\nThis project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!\n","funding_links":["https://github.com/sponsors/danpaz"],"categories":["JavaScript","Elasticsearch developer tools and utilities"],"sub_categories":["Development and debugging"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanpaz%2Fbodybuilder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdanpaz%2Fbodybuilder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanpaz%2Fbodybuilder/lists"}