repo.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. package repo
  2. import (
  3. "context"
  4. "copter-train/db"
  5. "copter-train/log"
  6. "fmt"
  7. "go.mongodb.org/mongo-driver/bson"
  8. "go.mongodb.org/mongo-driver/bson/primitive"
  9. "go.mongodb.org/mongo-driver/mongo"
  10. "go.mongodb.org/mongo-driver/mongo/options"
  11. )
  12. type RepoSession struct {
  13. Ctx context.Context
  14. Client *db.MongoDB
  15. }
  16. const (
  17. CollectionCategory = "category"
  18. CollectionUser = "users"
  19. )
  20. type Map map[string]interface{}
  21. type PageResult struct {
  22. List []map[string]interface{} `json:"list"`
  23. Total int64 `json:"total"`
  24. Page int64 `json:"page"`
  25. Size int64 `json:"size"`
  26. }
  27. type PageSearchOptions struct {
  28. CollectName string
  29. Page int64
  30. Size int64
  31. Query map[string]interface{}
  32. Project []string
  33. Sort interface{}
  34. }
  35. type DocSearchOptions struct {
  36. Db string
  37. CollectName string
  38. Query Map
  39. Project []string
  40. Sort bson.M
  41. }
  42. func NewDocSearchOptions(filter Map, project []string) *DocSearchOptions {
  43. return &DocSearchOptions{
  44. Query: filter,
  45. Project: project,
  46. }
  47. }
  48. func RepoAddDoc(ctx *RepoSession, collectName string, doc interface{}) (string, error) {
  49. users := ctx.Client.GetCollection(collectName)
  50. result, err := users.InsertOne(ctx.Ctx, doc)
  51. if err != nil {
  52. return "", err
  53. }
  54. return result.InsertedID.(primitive.ObjectID).Hex(), nil
  55. }
  56. func RepoDeleteDoc(ctx *RepoSession, collectName string, id string) (interface{}, error) {
  57. uid, _ := primitive.ObjectIDFromHex(id)
  58. colls := ctx.Client.GetCollection(collectName)
  59. return colls.DeleteOne(ctx.Ctx, &bson.M{"_id": uid})
  60. }
  61. func RepoDeleteDocs(ctx *RepoSession, collectName string, query interface{}) (interface{}, error) {
  62. colls := ctx.Client.GetCollection(collectName)
  63. return colls.DeleteMany(ctx.Ctx, query)
  64. }
  65. func RepoUpdateSetDocs(ctx *RepoSession, collectName string, filter interface{}, model interface{}) (*mongo.UpdateResult, error) {
  66. colls := ctx.Client.GetCollection(collectName)
  67. update := bson.M{"$set": model}
  68. return colls.UpdateOne(ctx.Ctx, filter, update)
  69. }
  70. func RepoUpdateSetDoc(ctx *RepoSession, collectName string, idstr string, model interface{}) (*mongo.UpdateResult, error) {
  71. colls := ctx.Client.GetCollection(collectName)
  72. update := bson.M{"$set": model}
  73. uid, _ := primitive.ObjectIDFromHex(idstr)
  74. return colls.UpdateByID(ctx.Ctx, uid, update)
  75. }
  76. func RepoUpsertSetDoc(ctx *RepoSession, collectName string, filter interface{}, model interface{}) (*mongo.UpdateResult, error) {
  77. coll := ctx.Client.GetCollection(collectName)
  78. update := bson.M{"$set": model}
  79. // filter := bson.D{{"type", "Oolong"}}
  80. // update := bson.D{{"$set", bson.D{}}}
  81. opts := options.Update().SetUpsert(true)
  82. return coll.UpdateOne(ctx.Ctx, filter, update, opts)
  83. }
  84. func RepoUpdateSetDocProps(ctx *RepoSession, collectName string, idstr string, update interface{}) (*mongo.UpdateResult, error) {
  85. colls := ctx.Client.GetCollection(collectName)
  86. // update := bson.M{"$set": model}
  87. uid, _ := primitive.ObjectIDFromHex(idstr)
  88. return colls.UpdateByID(ctx.Ctx, uid, update)
  89. }
  90. func RepoSeachDoc(ctx *RepoSession, param *DocSearchOptions, v interface{}) (bool, error) {
  91. colls := ctx.Client.GetDbCollection(param.Db, param.CollectName)
  92. opt := &options.FindOneOptions{}
  93. if param.Sort != nil {
  94. opt.SetSort(param.Sort)
  95. }
  96. if len(param.Project) > 0 {
  97. prj := bson.M{}
  98. for _, v := range param.Project {
  99. prj[v] = 1
  100. }
  101. opt.SetProjection(prj)
  102. }
  103. filter := bson.M{}
  104. if len(param.Query) > 0 {
  105. for k, v := range param.Query {
  106. if k == "_id" {
  107. if uid, ok := v.(string); ok {
  108. docId, _ := primitive.ObjectIDFromHex(uid)
  109. filter["_id"] = docId
  110. continue
  111. }
  112. }
  113. filter[k] = v
  114. }
  115. }
  116. err := colls.FindOne(ctx.Ctx, filter, opt).Decode(v)
  117. if err == mongo.ErrNoDocuments {
  118. return false, nil
  119. }
  120. if err != nil {
  121. return false, err
  122. }
  123. return true, nil
  124. }
  125. func RepoSeachDocs(ctx *RepoSession, param *DocSearchOptions, out interface{}) error {
  126. colls := ctx.Client.GetCollection(param.CollectName)
  127. opt := &options.FindOptions{}
  128. if len(param.Project) > 0 {
  129. prj := bson.M{}
  130. for _, v := range param.Project {
  131. prj[v] = 1
  132. }
  133. opt.SetProjection(prj)
  134. }
  135. filter := bson.M{}
  136. if len(param.Query) > 0 {
  137. for k, v := range param.Query {
  138. if k == "_id" {
  139. if uid, ok := v.(string); ok {
  140. docId, _ := primitive.ObjectIDFromHex(uid)
  141. filter["_id"] = docId
  142. continue
  143. }
  144. }
  145. filter[k] = v
  146. }
  147. }
  148. cur, err := colls.Find(ctx.Ctx, filter, opt)
  149. if err != nil {
  150. return err
  151. }
  152. defer cur.Close(ctx.Ctx)
  153. err = cur.All(ctx.Ctx, out)
  154. return err
  155. }
  156. func RepoSeachDocMap(ctx *RepoSession, param *DocSearchOptions) (bool, map[string]interface{}) {
  157. ret := map[string]interface{}{}
  158. ok := true
  159. colls := ctx.Client.GetCollection(param.CollectName)
  160. opt := &options.FindOneOptions{}
  161. if len(param.Project) > 0 {
  162. prj := bson.M{}
  163. for _, v := range param.Project {
  164. prj[v] = 1
  165. }
  166. opt.SetProjection(prj)
  167. }
  168. filter := bson.M{}
  169. if len(param.Query) > 0 {
  170. for k, v := range param.Query {
  171. if k == "_id" {
  172. if uid, ok := v.(string); ok {
  173. docId, _ := primitive.ObjectIDFromHex(uid)
  174. filter["_id"] = docId
  175. continue
  176. }
  177. }
  178. filter[k] = v
  179. }
  180. }
  181. ok = true
  182. err := colls.FindOne(ctx.Ctx, filter, opt).Decode(ret)
  183. if err == mongo.ErrNoDocuments {
  184. ok = false
  185. }
  186. if err != nil {
  187. ok = false
  188. }
  189. return ok, ret
  190. }
  191. // PageSearch 单表分页查询
  192. func RepoPageSearch(ctx *RepoSession, para *PageSearchOptions) (out *PageResult, err error) {
  193. colls := ctx.Client.GetCollection(para.CollectName)
  194. findoptions := &options.FindOptions{}
  195. if para.Size > 0 {
  196. findoptions.SetLimit(para.Size)
  197. findoptions.SetSkip(para.Size * (para.Page - 1))
  198. }
  199. if para.Sort != nil {
  200. findoptions.SetSort(para.Sort)
  201. }
  202. if len(para.Project) > 0 {
  203. prj := bson.M{}
  204. for _, v := range para.Project {
  205. prj[v] = 1
  206. }
  207. findoptions.SetProjection(prj)
  208. }
  209. filter := bson.M{}
  210. if len(para.Query) > 0 {
  211. for k, v := range para.Query {
  212. if value, ok := v.(string); ok {
  213. if len(value) > 0 {
  214. filter[k] = v
  215. continue
  216. }
  217. } else if v != nil {
  218. filter[k] = v
  219. }
  220. }
  221. }
  222. cur, err := colls.Find(ctx.Ctx, filter, findoptions)
  223. out = &PageResult{
  224. List: []map[string]interface{}{},
  225. Total: 0,
  226. Page: para.Page,
  227. Size: para.Size,
  228. }
  229. if err != nil {
  230. return out, err
  231. }
  232. defer cur.Close(ctx.Ctx)
  233. err = cur.All(ctx.Ctx, &out.List)
  234. out.Total, _ = colls.CountDocuments(ctx.Ctx, filter)
  235. return
  236. }
  237. // PageSearch 单表分页查询
  238. func RepoCountDoc(ctx *RepoSession, collectionName string, Query Map) (int64, error) {
  239. colls := ctx.Client.GetCollection(collectionName)
  240. filter := bson.M{}
  241. if len(Query) > 0 {
  242. for k, v := range Query {
  243. if value, ok := v.(string); ok {
  244. if len(value) > 0 {
  245. filter[k] = v
  246. continue
  247. }
  248. } else {
  249. filter[k] = v
  250. }
  251. }
  252. }
  253. return colls.CountDocuments(ctx.Ctx, filter)
  254. }
  255. // PageSearch 单表分页查询
  256. func RepoDocsSearch(ctx *RepoSession, para *PageSearchOptions, out interface{}) (err error) {
  257. colls := ctx.Client.GetCollection(para.CollectName)
  258. findoptions := &options.FindOptions{}
  259. if para.Size > 0 {
  260. findoptions.SetLimit(para.Size)
  261. findoptions.SetSkip(para.Size * (para.Page - 1))
  262. }
  263. if para.Sort != nil {
  264. findoptions.SetSort(para.Sort)
  265. }
  266. if len(para.Project) > 0 {
  267. prj := bson.M{}
  268. for _, v := range para.Project {
  269. prj[v] = 1
  270. }
  271. findoptions.SetProjection(prj)
  272. }
  273. filter := bson.M{}
  274. if len(para.Query) > 0 {
  275. for k, v := range para.Query {
  276. if value, ok := v.(string); ok {
  277. if len(value) > 0 {
  278. filter[k] = v
  279. continue
  280. }
  281. } else {
  282. filter[k] = v
  283. }
  284. }
  285. }
  286. cur, err := colls.Find(ctx.Ctx, filter, findoptions)
  287. if err != nil {
  288. return err
  289. }
  290. defer cur.Close(ctx.Ctx)
  291. err = cur.All(ctx.Ctx, out)
  292. return
  293. }
  294. func RepoDocArrayAppend(ctx *RepoSession, collectName string, idstr string, fieldpath string, arrayItem interface{}) (*mongo.UpdateResult, error) {
  295. colls := ctx.Client.GetCollection(collectName)
  296. arrayOp := bson.M{}
  297. arrayOp[fieldpath] = arrayItem
  298. update := bson.M{"$push": arrayOp}
  299. uid, _ := primitive.ObjectIDFromHex(idstr)
  300. return colls.UpdateByID(ctx.Ctx, uid, update)
  301. }
  302. // { _id: 4, "grades.grade": 85 },
  303. // { $set: { "grades.$.std" : 6 } }
  304. type ArrayOneUpdateOption struct {
  305. Query Map
  306. Set Map
  307. CollectName string
  308. Id string
  309. }
  310. func RepoDocArrayOneUpdate(ctx *RepoSession, options *ArrayOneUpdateOption) (*mongo.UpdateResult, error) {
  311. colls := ctx.Client.GetCollection(options.CollectName)
  312. docId, _ := primitive.ObjectIDFromHex(options.Id)
  313. query := bson.M{"_id": docId}
  314. if len(options.Query) > 0 {
  315. for k, v := range options.Query {
  316. query[k] = v
  317. }
  318. }
  319. setOp := bson.M{}
  320. for k, v := range options.Set {
  321. setOp[k] = v
  322. }
  323. update := bson.M{"$set": setOp}
  324. return colls.UpdateOne(ctx.Ctx, query, update)
  325. }
  326. type ArrayOneRemoveOption struct {
  327. ArrayQuery Map
  328. CollectName string
  329. Id string
  330. }
  331. // { $pull: { "items" : { id: 23 } } }
  332. func RepoDocArrayOneRemove(ctx *RepoSession, options *ArrayOneRemoveOption) (*mongo.UpdateResult, error) {
  333. colls := ctx.Client.GetCollection(options.CollectName)
  334. docId, _ := primitive.ObjectIDFromHex(options.Id)
  335. query := bson.M{"_id": docId}
  336. arrayQuery := bson.M{}
  337. if len(options.ArrayQuery) > 0 {
  338. for k, v := range options.ArrayQuery {
  339. arrayQuery[k] = v
  340. }
  341. }
  342. update := bson.M{"$pull": arrayQuery}
  343. return colls.UpdateOne(ctx.Ctx, query, update)
  344. }
  345. type ArrayOneSearchOption struct {
  346. ArrayQuery Map
  347. CollectName string
  348. Id string
  349. Field string
  350. }
  351. func RepoDocArraySearch(ctx *RepoSession, options *ArrayOneSearchOption) (ok bool, ret map[string]interface{}) {
  352. colls := ctx.Client.GetCollection(options.CollectName)
  353. docId, _ := primitive.ObjectIDFromHex(options.Id)
  354. match := []bson.E{}
  355. match = append(match, bson.E{Key: "_id", Value: docId})
  356. if len(options.ArrayQuery) > 0 {
  357. for k, v := range options.ArrayQuery {
  358. match = append(match, bson.E{Key: k, Value: v})
  359. }
  360. }
  361. matchStage := bson.D{
  362. {Key: "$match", Value: match},
  363. }
  364. unwindStage := bson.D{
  365. {Key: "$unwind", Value: fmt.Sprintf("%s%s", "$", options.Field)},
  366. }
  367. curr, err := colls.Aggregate(ctx.Ctx, mongo.Pipeline{matchStage, unwindStage})
  368. if err != nil {
  369. ok = false
  370. return
  371. }
  372. defer curr.Close(ctx.Ctx)
  373. var list []map[string]interface{}
  374. err = curr.All(ctx.Ctx, list)
  375. if err != nil {
  376. ok = false
  377. return
  378. }
  379. ok = true
  380. ret = list[0]
  381. return
  382. }
  383. type DocsSearchOptions struct {
  384. CollectName string
  385. Query map[string]interface{}
  386. Project []string
  387. Sort interface{} //bson.D{ bson.E{"update_time", -1}, bson.E{"goods_id", -1},}
  388. }
  389. func RepoSeachDocsMap(ctx *RepoSession, param *DocsSearchOptions) (ok bool, list []map[string]interface{}) {
  390. colls := ctx.Client.GetCollection(param.CollectName)
  391. findoptions := &options.FindOptions{}
  392. if len(param.Project) > 0 {
  393. prj := bson.M{}
  394. for _, v := range param.Project {
  395. prj[v] = 1
  396. }
  397. findoptions.SetProjection(prj)
  398. }
  399. if param.Sort != nil {
  400. findoptions.SetSort(param.Sort)
  401. }
  402. filter := bson.M{}
  403. if len(param.Query) > 0 {
  404. for k, v := range param.Query {
  405. if value, ok := v.(string); ok {
  406. if len(value) > 0 {
  407. filter[k] = v
  408. continue
  409. }
  410. } else {
  411. filter[k] = v
  412. }
  413. }
  414. }
  415. cur, err := colls.Find(ctx.Ctx, filter, findoptions)
  416. if err != nil {
  417. ok = false
  418. return
  419. }
  420. defer cur.Close(ctx.Ctx)
  421. listRes := []map[string]interface{}{}
  422. err = cur.All(ctx.Ctx, &listRes)
  423. if err != nil {
  424. log.Error(err)
  425. ok = false
  426. return
  427. }
  428. list = listRes
  429. ok = true
  430. return
  431. }