{"id":18509961,"url":"https://github.com/archywillhe/db-butler","last_synced_at":"2025-05-14T11:13:50.514Z","repository":{"id":28863764,"uuid":"32387911","full_name":"archywillhe/DB-Butler","owner":"archywillhe","description":"(project abandoned) flexible ODM and hooks for meteor's MongoDB","archived":false,"fork":false,"pushed_at":"2015-04-01T00:19:17.000Z","size":216,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-17T02:41:32.254Z","etag":null,"topics":["abandoned"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/archywillhe.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-03-17T10:51:58.000Z","updated_at":"2017-06-25T16:18:44.000Z","dependencies_parsed_at":"2022-09-08T00:40:58.995Z","dependency_job_id":null,"html_url":"https://github.com/archywillhe/DB-Butler","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/archywillhe%2FDB-Butler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/archywillhe%2FDB-Butler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/archywillhe%2FDB-Butler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/archywillhe%2FDB-Butler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/archywillhe","download_url":"https://codeload.github.com/archywillhe/DB-Butler/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254129537,"owners_count":22019629,"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":["abandoned"],"created_at":"2024-11-06T15:19:50.793Z","updated_at":"2025-05-14T11:13:50.460Z","avatar_url":"https://github.com/archywillhe.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"## What is DBButler? ##\n\nDBButler manages your Mongo Collections in Meteor. It is basically a library that provides flexible ODM (Object-documenet mapping), hooks, a bunch of useful functional programming helpers, and better coding convention.\n\nIt is designed in a way that it's flexible for humans to use, the same time can also be seamlessly integrated into \u003ca target=\"_blank\" href=\"http://archy.io\"\u003eArchy\u003c/a\u003e, a Meteor app that builds Meteor apps for you.\n\n\n## Why uses DBButler? ##\n\nIt is written in vanilla JavaScript (I'm pretty anti-coffeeScript :D ) with closures \u0026 prototypes. It does not pretend to be class-based OO. \n\nAnd it is super easy to use!\n\nCheck out the docs \u003ca target=\"_blank\" href=\"http://butler.archy.io/api\"\u003ehere\u003c/a\u003e and tutorial \u003ca target=\"_blank\" href=\"http://butler.archy.io/tutorial\"\u003ehere\u003c/a\u003e.\n\n\n## Quickstart ##\n\n```\nmeteor add arch:db-butler\n```\n\n##1. Create a collection \u0026 Insert a document ##\n\nTo create a collection (with `prepare()`) and insert a record (with `insert()`):\n\n```javascript\nDBButler.prepare(\"book\"); //this creates a new Mongo.Collection(\"book\")\nDBButler.insert({\"title\":\"on anarchism\"}); \n//this line above will insert into the latest collection DBButler interacted with\n//in this case it is the \"book\" collection.\n```\n\n## 2. Edit some document in a collection ##\n\nTo edit a field of some documents in your collection, you can use `.edit()`.\n```javascript\nDBButler.edit(\"cat\",{\"name\":\"nyanCat\"},{\"furColor\":\"white\"}); \n//this would change the furColor to \"white\" for the documents in \"cat\" collections that have name \"nyanCat\".\n```\nOr simply do this (if the last collection we interacted was \"cat\")\n\n```javascript\nDBButler.edit({\"name\":\"nyanCat\"},{\"furColor\":\"white\"}); \n```\n\nRead the docs on flexiablity \u003ca\u003ehere\u003c/a\u003e to learn more about how you can utilize it.\n\n## 3. Declaring One-to-many / Many-to-one Relation + inserting ##\n\nFor one-to-many: use `.hasMany()`. To insert a document with relation: use `.find().insert()`.\n\n```javascript\nDBButler.prepare(\"author\").hasMany(\"book\");\nvar NoamChomskyId = DBButler.insert({name:\"Noam Chomsky\"});\nDBButler.find(\"author\",NoamChomskyId).insert(\"book\",{\"title\":\"on anarchism\"}); \n//this will wait until \"book\" is prepared and then\n//insert {\"title\":\"on anarchism\"} into \"book\" with foreign key \"authorId\"\n//if there is no Noam Chomsky in \"author\", the default behavior is to throw an error\nDBButler.prepare(\"book\");\n```\n\n\u003eNote: Unlike `Mongo.collection.find`, `DBButler.find` does not return a cursor; DBButler.find does not do any db operations, what it does is just to prepare an object that has relational-mapping functions like `.insert`, which is different from `DBButler.insert`.\n\n\nFor many-to-one, which is just the reverse, use `.hasOne()`\n```javascript\nDBButler.prepare(\"book\").hasOne(\"author\");\n```\n\n\u003eFor many-to-one/one-to-many relation, By default we take the approach of normalizing data: so foreginKey for referencing would be used. \n\nIf you want to store the \"many\" as an array for a key in the \"one\":\n\n```javascript\nDBButler.prepare(\"book\").hasOne(\"author\",{denormalizing:true});\n```\n\n\n## 4. Getting or updating relational data ##\n\nGet an array of books whose author is Noam Chomsky:\n\n```javascript\nDBButler.find(\"author\",NoamChomskyId).get(\"book\");\n//or\nDBButler.find(\"author\",NoamChomskyId).book(); \n```\n\nUpdate Noam Chomsky's books:\n\n```javascript\nDBButler.find(\"author\",NoamChomskyId).edit(\"book\",{\"awesome\":true});\n//or\nDBButler.find(\"author\",NoamChomskyId).book(\"edit\",{\"awesome\":true}); \n```\n\n##5. One-to-one Relation ##\n\n```javascript\nDBButler.prepare(\"user\").oneToOne(\"profile\");\n```\n\n\u003eFor one-to-one relation, by default we take the approach of denormalizing data: so profile would just be a key of user docuement:  there would only be 1 collection. In the case above, `DBButler.prepare(\"profile\")` would not do anything.\n\nTo minimize data redundancy \u0026 store \"user\" and \"profile\" in separate collections\"\n\n```javascript\nDBButler.prepare(\"user\").ontToOne(\"profile\",{denormalizing:true});\n```\n\n\n## 6. ManyToMany Relation ##\n\nFor all many to many relation, a junction collection is created by default.\n\n```javascript\nDBButle.prepare(\"programmer\").manyToMany(\"languages\"); //this would not only create programmer collection, but programmer_langauges collection (that works as a junction table)\nvar archyID = DBButler.insert({\"name\":\"Archy\"});\nDBButler.find(\"programmer\",archyID).insert(\"languages\",\n    [{name: \"Javascript\",OO:\"prototype-based\"},\n    {name: \"Haskell\",functional:\"purely\"},\n    {name: \"PHP\", OO:\"class-based\"},\n    {name: \"Ruby\", OO:\"class-based\"},\n    {name: \"Obj-C\", OO:\"class-based\"},\n    {name: \"HTML\", declarative:true}]);\n); \n//this would insert 6 docuements into languages collections\n//and the same time 6 docuements about the relation into programmer_langauges collection\nDBButle.prepare(\"languages\"); \n\n//note: the insert statement would not insert anything to \"languages\" if we just pass an array of languages id as the 2nd arguement like this:\nDBButler.find(\"programmer\",archyID).insert(\"languages\", [\"asdasd231\",\"sxzsc23\"]);\n//this would simply insert 2 docuements about the realtion into programmer_langauges collection if docuements with id \"asdasd231\",\"sxzsc23\" exist in languages collection\n```\n\nThis behavior can once again be altered by passing `{denormalizing:\"weak\"}` or `{denormalizing:\"strong\"}` to the 2nd parameter (default value for denormalizing for many-to-many relation is `false`).\n\nRead the doc to learn more.\n\n## 7. Hooks ##\n\nHooks are pretty straightforward. They are functions to be called before or after some DBButler event, with `.before()` and `.after()`.\n\n\n```javascript\nDBButler.assigned(\"cats\");\nDBButler.after(\"find\",function(){\n    //call after every cats find event\n}).before(\"insert\",function(){\n    //call before every cats insert event\n});\n```\nYou can be more detailed on when the function should be called:\n\n```javascript\nDBButler.assigned(\"cats\");\nDBButler.after(\"find\",{\"name\":\"NyanCat\"},function(){\n    //call only when finding docuement with name as \"NyanCat\".\n});\n```\n\n\u003eNote: since `.get()` uses `.find()`. function attaching to \"find\" would be called for \"get\" event as well.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farchywillhe%2Fdb-butler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farchywillhe%2Fdb-butler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farchywillhe%2Fdb-butler/lists"}