{"id":13411862,"url":"https://github.com/ostafen/clover","last_synced_at":"2025-05-14T19:09:56.528Z","repository":{"id":37401441,"uuid":"453191009","full_name":"ostafen/clover","owner":"ostafen","description":"A lightweight document-oriented NoSQL database written in pure Golang.","archived":false,"fork":false,"pushed_at":"2025-02-12T11:06:47.000Z","size":1519,"stargazers_count":740,"open_issues_count":21,"forks_count":60,"subscribers_count":12,"default_branch":"v2","last_synced_at":"2025-04-13T15:08:41.487Z","etag":null,"topics":["badger","boltdb","database","document-oriented-database","embedded-database","golang","json","nosql","nosql-database"],"latest_commit_sha":null,"homepage":"","language":"Go","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/ostafen.png","metadata":{"files":{"readme":"README-CN.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["ostafen"]}},"created_at":"2022-01-28T19:25:23.000Z","updated_at":"2025-04-10T12:08:31.000Z","dependencies_parsed_at":"2023-02-18T06:01:21.780Z","dependency_job_id":"b97f6385-cc7c-4ba8-9ccf-eec079f8ac5a","html_url":"https://github.com/ostafen/clover","commit_stats":{"total_commits":267,"total_committers":27,"mean_commits":9.88888888888889,"dds":"0.17228464419475653","last_synced_commit":"2b3279fdcad38827de3620cda4eb1748d1ebdddd"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ostafen%2Fclover","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ostafen%2Fclover/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ostafen%2Fclover/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ostafen%2Fclover/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ostafen","download_url":"https://codeload.github.com/ostafen/clover/tar.gz/refs/heads/v2","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254209859,"owners_count":22032897,"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":["badger","boltdb","database","document-oriented-database","embedded-database","golang","json","nosql","nosql-database"],"created_at":"2024-07-30T20:01:17.726Z","updated_at":"2025-05-14T19:09:55.326Z","avatar_url":"https://github.com/ostafen.png","language":"Go","readme":"\u003cp align=\"center\"\u003e\n\u003cimg alt=\"CloverDB Logo\" src=\".github/logo.png#gh-light-mode-only\" width=\"300px\"\u003e\n\u003cimg alt=\"CloverDB Logo\" src=\".github/logo-white.png#gh-dark-mode-only\" width=\"300px\"\u003e\n\u003c/p\u003e\n\u003ch2 align=\"center\"\u003e轻量级面向文档的NoSQL数据库\u003c/h2\u003e\n\n[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go)  \n[![Go Reference](https://pkg.go.dev/badge/badge/github.com/ostafen/clover.svg)](https://pkg.go.dev/github.com/ostafen/clover)\n[![Go Report Card](https://goreportcard.com/badge/github.com/ostafen/clover)](https://goreportcard.com/report/github.com/ostafen/clover)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)\n[![codecov](https://codecov.io/gh/ostafen/clover/branch/main/graph/badge.svg?token=R06H8FR47O)](https://codecov.io/gh/ostafen/clover)\n[![Join the chat at https://gitter.im/cloverDB/community](https://badges.gitter.im/cloverDB/community.svg)](https://gitter.im/cloverDB/community?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n\n\u003e [🇬🇧 English](README.md) | 🇨🇳 简体中文 | [🇪🇸 Spanish](README-ES.md) \n\n**CloverDB** 是一个轻量级的NoSQL数据库，由于它的代码库很小，所以设计得简单且易于维护。它的灵感来自 [tinyDB](https://github.com/msiemens/tinydb).\n\n## 特点\n\n- 面向文档\n- 原生Golang编写\n- 简单直观的api\n- 容易维护\n\n## 为什么选择CloverDB?\n\n编写**CloverDB**是为了使其易于维护。因此，它以简单性换取性能，并不是为了替代性能更好的数据库，如**MongoDB**或**MySQL**。然而，在有些项目中，运行单独的数据库服务器可能会导致过度消耗，并且，对于简单的查询，网络延迟可能是主要的性能瓶颈。对于这个场景，**cloverDB**可能是一个更合适的替代方案。\n\n## 数据层\n\n**CloverDB**通过**StorageEngine**抽象的方式将集合存储在磁盘上。默认的实现基于[Badger](https://github.com/dgraph-io/badger)数据库键值存储。不管怎样\n，您可以轻松地编写自己的存储引擎实现。\n\n## 安装\n确保你拥有Go运行环境 (需要Go 1.13 或者更高版本)\n```shell\n  GO111MODULE=on go get github.com/ostafen/clover\n```\n\n## 数据库和集合\nCloverDB将数据记录存储为JSON“文档”，这些“文档“被分组在集合中。数据库由一个或多个集合组成。\n以下简称“文档”为文档\n\n### 数据库\n要在集合中存储文档，必须使用open()函数打开Clover数据库。 \n```go\nimport (\n\t\"log\"\n\tc \"github.com/ostafen/clover\"\n)\n\n...\n\ndb, _ := c.Open(\"clover-db\")\n\n// 或者，如果你不需要持久性，则像下面这样设置开启内存数据库模式\ndb, _ := c.Open(\"\", c.InMemoryMode(true))\n\ndefer db.Close() // 记住当你完成时关闭数据库\n```\n\n### 集合\nCloverDB将文档存储在集合中。集合是关系数据库中的表的无模式对等物。集合是通过调用数据库实例上的CreateCollection()函数创建的。可以使用Insert()或InsertOne()方法插入新文档。每个文档都由存储在id特殊字段中的Version 4 UUID唯一标识，并在插入期间生成。\n\n```go\n\ndb, _ := c.Open(\"clover-db\")\ndb.CreateCollection(\"myCollection\") // 创建一个名为\"mycollection\"的新集合\n\n// 在集合中插入一个新文档\ndoc := c.NewDocument()\ndoc.Set(\"hello\", \"clover!\")\n\n// Insertone返回插入文档的ID，此处执行将doc插入到\"myCollection\"这个collection中\ndocId, _ := db.InsertOne(\"myCollection\", doc)\nfmt.Println(docId)\n\n```\n### 引入与导出集合\nCloverDB能够轻松地将集合导入和导出为JSON格式，而不管使用的是哪种存储引擎。\n```go\n// 将\"todos\"集合的内容转储到\"todos.json\"文件\ndb.ExportCollection(\"todos\", \"todos.json\")\n\n...\n\n// 从导出的json文件中恢复todos集合\ndb.DropCollection(\"todos\")\ndb.ImportCollection(\"todos\", \"todos.json\")\n\ndocs, _ := db.Query(\"todos\").FindAll()\nfor _, doc := range docs {\n  log.Println(doc)\n}\n\n```\n\n\n## 请求\nCloverDB配备了流利而优雅的API来查询您的数据。查询由查询对象表示，该对象允许检索与给定标准匹配的文档。可以通过将有效的集合名称传递给query()方法来创建查询。\n\n\n### 选择集合中的所有文档\nFindAll()方法用于检索满足给定查询的所有文档。\n```go\ndocs, _ := db.Query(\"myCollection\").FindAll()\n\ntodo := \u0026struct {\n    Completed bool   `clover:\"completed\"`\n    Title     string `clover:\"title\"`\n    UserId    int    `clover:\"userId\"`\n}{}\n\nfor _, doc := range docs {\n    doc.Unmarshal(todo)\n    log.Println(todo)\n}\n```\n### 筛选器文档与标准\n为了过滤FindAll()返回的文档，必须使用Where()方法指定查询标准。标准对象只是表示文档上的谓词，只有当文档满足所有查询条件时才计算为true。\n\n下面的示例展示了如何构建一个简单的标准，以匹配所有completed字段等于true的文档。\n\n```go\ndb.Query(\"todos\").Where(c.Field(\"completed\").Eq(true)).FindAll()\n\n// 等效于\ndb.Query(\"todos\").Where(c.Field(\"completed\").IsTrue()).FindAll()\n```\n\n为了构建非常复杂的查询，我们使用And()和Or()方法链接多个标准对象，每个对象返回一个通过应用相应的逻辑运算符获得的新标准。\n```go\n//查找id为5和8的用户的所有已完成的待办事项\ndb.Query(\"todos\").Where(c.Field(\"completed\").Eq(true).And(c.Field(\"userId\").In(5, 8))).FindAll()\n```\n\n### 排序文档\n要对CloverDB中的文档进行排序，您需要使用sort()。它是一个可变函数，接受SortOption序列，每个序列允许指定一个字段和一个排序方向。排序方向可以为1或-1，分别对应升序和降序。如果没有提供SortOption, Sort()默认使用id字段。\n\n```go\n// 找到属于最近插入的用户的任何待办事项\ndb.Query(\"todos\").Sort(c.SortOption{\"userId\", -1}).FindFirst()\n```\n### 跳过/限制文档\n有时，从输出中跳过一些文档，或者简单地设置查询返回结果的最大数量可能很有用。为此，CloverDB提供了Skip()和Limit()函数，它们都接受整数$n$作为参数。\n```go\n// 丢弃输出中的前10个文档\n// 还将查询结果的最大数量限制为100个\ndb.Query(\"todos\").Skip(10).Limit(100).FindAll()\n```\n\n\n### 更新和删除文档\nUpdate()方法用于修改集合中文档的特定字段。delete()方法用于删除文档。两种方法都属于查询对象，因此易于更新和删除与特定查询匹配的文档。\n```go\n// 将id为1的用户的所有待办事项标记为已完成\nupdates := make(map[string]interface{})\nupdates[\"completed\"] = true\n\ndb.Query(\"todos\").Where(c.Field(\"userId\").Eq(1)).Update(updates)\n\n// 删除id为5和8的用户的所有待办事项\ndb.Query(\"todos\").Where(c.Field(\"userId\").In(5,8)).Delete()\n```\n\n要使用特定的文档id更新或删除单个文档，请分别使用UpdateById()或DeleteById(),\n顺序为:\n\n```go\ndocId := \"1dbce353-d3c6-43b3-b5a8-80d8d876389b\"\n// 使用指定的id更新文档\ndb.Query(\"todos\").UpdateById(docId, map[string]interface{}{\"completed\": true})\n// or delete it\ndb.Query(\"todos\").DeleteById(docId)\n```\n\n\n## 数据类型\nCloverDB内部支持以下原始数据类型：**int64**、**uint64**、**flat64**、**string**、**bool** 和 **time.Time**。CloverDB会尝试对非内部类型进行转化：有符号整数值被转换为int64、而无符号整数值被转换为uint64、Float32值扩展为Float64。\n\n\n例如，以下代码中的`uint8`类型的值会被CloverDB自动转化：\n\n```go\ndoc := c.NewDocument()\ndoc.Set(\"myField\", uint8(10)) // \"myField\" 被自动转为 uint64 类型\n\nfmt.Println(doc.Get(\"myField\").(uint64))\n```\n\n关于指针，将会自动迭代引用，直到迭代出空指针`nil`，或者非指针类型停止：\n\n``` go\nvar x int = 10\nvar ptr *int = \u0026x\nvar ptr1 **int = \u0026ptr\n\ndoc.Set(\"ptr\", ptr) // ptr自动迭代指针引用，存入的值为10，下面同理\ndoc.Set(\"ptr1\", ptr1) \n\nfmt.Println(doc.Get(\"ptr\").(int64) == 10) // 比较结果为 true\nfmt.Println(doc.Get(\"ptr1\").(int64) == 10)\n\nptr = nil\n\ndoc.Set(\"ptr1\", ptr1)\n// ptr1为指向ptr的指针，但ptr是一个空指针，所以最终迭代到nil停止，存入值为nil，下方判断为true\nfmt.Println(doc.Get(\"ptr1\") == nil)\n```\n\n非法数据类型将会被直接丢弃，不触发存入：\n\n```go\ndoc := c.NewDocument()\ndoc.Set(\"myField\", make(chan struct{})) // 由于chan非法，所以直接丢弃，不会触发存入\n\nlog.Println(doc.Has(\"myField\")) // 这里将会直接打印false\n```\n\n## 贡献\n\n**CloverDB** 正在积极开发中。任何以建议、错误报告或拉请求的形式做出的贡献，都是可以接受的。 :blush:\n\n很感激收到的来自下面名单的主要贡献及建议(按字母顺序排列)：\n\n- [ASWLaunchs](https://github.com/ASWLaunchs)\n- [jsgm](https://github.com/jsgm)\n- [segfault99](https://github.com/segfault99)\n","funding_links":["https://github.com/sponsors/ostafen"],"categories":["Database","Databases","Go","Generators","数据库","Data Integration Frameworks"],"sub_categories":["Databases Implemented in Go","NoSQL, Document Databases","Go中实现的数据库"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fostafen%2Fclover","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fostafen%2Fclover","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fostafen%2Fclover/lists"}