repo.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. package repo
  2. import (
  3. "context"
  4. "fmt"
  5. "oilseal-train/db"
  6. "oilseal-train/log"
  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. CollectionUser = "users"
  18. )
  19. type Map map[string]interface{}
  20. type PageResult struct {
  21. List []map[string]interface{} `json:"list"`
  22. Total int64 `json:"total"`
  23. Page int64 `json:"page"`
  24. Size int64 `json:"size"`
  25. }
  26. type PageSearchOptions struct {
  27. Db string
  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 RepoDbAddDoc(ctx *RepoSession, dbName string, collectName string, doc interface{}) (string, error) {
  57. users := ctx.Client.GetDbCollection(dbName, collectName)
  58. result, err := users.InsertOne(ctx.Ctx, doc)
  59. if err != nil {
  60. return "", err
  61. }
  62. return result.InsertedID.(primitive.ObjectID).Hex(), nil
  63. }
  64. func RepoDeleteDoc(ctx *RepoSession, collectName string, id string) (interface{}, error) {
  65. uid, _ := primitive.ObjectIDFromHex(id)
  66. colls := ctx.Client.GetCollection(collectName)
  67. return colls.DeleteOne(ctx.Ctx, &bson.M{"_id": uid})
  68. }
  69. func RepoDeleteDbDoc(ctx *RepoSession, dbName string, collectName string, id string) (interface{}, error) {
  70. uid, _ := primitive.ObjectIDFromHex(id)
  71. colls := ctx.Client.GetDbCollection(dbName, collectName)
  72. return colls.DeleteOne(ctx.Ctx, &bson.M{"_id": uid})
  73. }
  74. func RepoDeleteDocs(ctx *RepoSession, collectName string, query interface{}) (interface{}, error) {
  75. colls := ctx.Client.GetCollection(collectName)
  76. return colls.DeleteMany(ctx.Ctx, query)
  77. }
  78. func RepoUpdateSetDoc(ctx *RepoSession, collectName string, idstr string, model interface{}) (*mongo.UpdateResult, error) {
  79. colls := ctx.Client.GetCollection(collectName)
  80. update := bson.M{"$set": model}
  81. uid, _ := primitive.ObjectIDFromHex(idstr)
  82. return colls.UpdateByID(ctx.Ctx, uid, update)
  83. }
  84. func RepoUpdateSeDbDoc(ctx *RepoSession, db string, collectName string, idstr string, model interface{}) (*mongo.UpdateResult, error) {
  85. colls := ctx.Client.GetDbCollection(db, collectName)
  86. update := bson.M{"$set": model}
  87. uid, _ := primitive.ObjectIDFromHex(idstr)
  88. return colls.UpdateByID(ctx.Ctx, uid, update)
  89. }
  90. func RepoUpdateSetDocProps(ctx *RepoSession, collectName string, idstr string, update interface{}) (*mongo.UpdateResult, error) {
  91. colls := ctx.Client.GetCollection(collectName)
  92. // update := bson.M{"$set": model}
  93. uid, _ := primitive.ObjectIDFromHex(idstr)
  94. return colls.UpdateByID(ctx.Ctx, uid, update)
  95. }
  96. func RepoUpdateSetDbDocProps(ctx *RepoSession, db string, collectName string, idstr string, update interface{}) (*mongo.UpdateResult, error) {
  97. colls := ctx.Client.GetDbCollection(db, collectName)
  98. // update := bson.M{"$set": model}
  99. uid, _ := primitive.ObjectIDFromHex(idstr)
  100. return colls.UpdateByID(ctx.Ctx, uid, update)
  101. }
  102. func RepoSeachDoc(ctx *RepoSession, param *DocSearchOptions, v interface{}) (bool, error) {
  103. colls := ctx.Client.GetDbCollection(param.Db, param.CollectName)
  104. opt := &options.FindOneOptions{}
  105. if len(param.Project) > 0 {
  106. prj := bson.M{}
  107. for _, v := range param.Project {
  108. prj[v] = 1
  109. }
  110. opt.SetProjection(prj)
  111. }
  112. filter := bson.M{}
  113. if len(param.Query) > 0 {
  114. for k, v := range param.Query {
  115. if k == "_id" {
  116. if uid, ok := v.(string); ok {
  117. docId, _ := primitive.ObjectIDFromHex(uid)
  118. filter["_id"] = docId
  119. continue
  120. }
  121. }
  122. filter[k] = v
  123. }
  124. }
  125. err := colls.FindOne(ctx.Ctx, filter, opt).Decode(v)
  126. if err == mongo.ErrNoDocuments {
  127. return false, nil
  128. }
  129. if err != nil {
  130. return false, err
  131. }
  132. return true, nil
  133. }
  134. func RepoSeachDocMap(ctx *RepoSession, param *DocSearchOptions) (bool, map[string]interface{}) {
  135. ret := map[string]interface{}{}
  136. ok := true
  137. colls := ctx.Client.GetDbCollection(param.Db, param.CollectName)
  138. opt := &options.FindOneOptions{}
  139. if len(param.Project) > 0 {
  140. prj := bson.M{}
  141. for _, v := range param.Project {
  142. prj[v] = 1
  143. }
  144. opt.SetProjection(prj)
  145. }
  146. filter := bson.M{}
  147. if len(param.Query) > 0 {
  148. for k, v := range param.Query {
  149. if k == "_id" {
  150. if uid, ok := v.(string); ok {
  151. docId, _ := primitive.ObjectIDFromHex(uid)
  152. filter["_id"] = docId
  153. continue
  154. }
  155. }
  156. filter[k] = v
  157. }
  158. }
  159. ok = true
  160. err := colls.FindOne(ctx.Ctx, filter, opt).Decode(ret)
  161. if err == mongo.ErrNoDocuments {
  162. ok = false
  163. }
  164. if err != nil {
  165. ok = false
  166. }
  167. return ok, ret
  168. }
  169. // PageSearch 单表分页查询
  170. func RepoPageSearch(ctx *RepoSession, para *PageSearchOptions) (out *PageResult, err error) {
  171. var colls *mongo.Collection
  172. if len(para.Db) > 0 {
  173. colls = ctx.Client.GetDbCollection(para.Db, para.CollectName)
  174. } else {
  175. colls = ctx.Client.GetCollection(para.CollectName)
  176. }
  177. findoptions := &options.FindOptions{}
  178. if para.Size > 0 {
  179. findoptions.SetLimit(para.Size)
  180. findoptions.SetSkip(para.Size * (para.Page - 1))
  181. }
  182. if para.Sort != nil {
  183. findoptions.SetSort(para.Sort)
  184. }
  185. if len(para.Project) > 0 {
  186. prj := bson.M{}
  187. for _, v := range para.Project {
  188. prj[v] = 1
  189. }
  190. findoptions.SetProjection(prj)
  191. }
  192. filter := bson.M{}
  193. if len(para.Query) > 0 {
  194. for k, v := range para.Query {
  195. if value, ok := v.(string); ok {
  196. if len(value) > 0 {
  197. filter[k] = v
  198. continue
  199. }
  200. } else if v != nil {
  201. filter[k] = v
  202. }
  203. }
  204. }
  205. cur, err := colls.Find(ctx.Ctx, filter, findoptions)
  206. out = &PageResult{
  207. List: []map[string]interface{}{},
  208. Total: 0,
  209. Page: para.Page,
  210. Size: para.Size,
  211. }
  212. if err != nil {
  213. return out, err
  214. }
  215. defer cur.Close(ctx.Ctx)
  216. err = cur.All(ctx.Ctx, &out.List)
  217. out.Total, _ = colls.CountDocuments(ctx.Ctx, filter)
  218. return
  219. }
  220. func RepoDbCountDoc(ctx *RepoSession, db string, collectionName string, Query Map) (int64, error) {
  221. colls := ctx.Client.GetDbCollection(db, collectionName)
  222. filter := bson.M{}
  223. if len(Query) > 0 {
  224. for k, v := range Query {
  225. if value, ok := v.(string); ok {
  226. if len(value) > 0 {
  227. filter[k] = v
  228. continue
  229. }
  230. } else {
  231. filter[k] = v
  232. }
  233. }
  234. }
  235. return colls.CountDocuments(ctx.Ctx, filter)
  236. }
  237. func RepoCountDoc(ctx *RepoSession, collectionName string, Query Map) (int64, error) {
  238. colls := ctx.Client.GetCollection(collectionName)
  239. filter := bson.M{}
  240. if len(Query) > 0 {
  241. for k, v := range Query {
  242. if value, ok := v.(string); ok {
  243. if len(value) > 0 {
  244. filter[k] = v
  245. continue
  246. }
  247. } else {
  248. filter[k] = v
  249. }
  250. }
  251. }
  252. return colls.CountDocuments(ctx.Ctx, filter)
  253. }
  254. // PageSearch 单表分页查询
  255. func RepoDocsSearch(ctx *RepoSession, para *PageSearchOptions, out interface{}) (err error) {
  256. colls := ctx.Client.GetCollection(para.CollectName)
  257. if len(para.Db) > 0 {
  258. colls = ctx.Client.GetDbCollection(para.Db, para.CollectName)
  259. }
  260. findoptions := &options.FindOptions{}
  261. if para.Size > 0 {
  262. findoptions.SetLimit(para.Size)
  263. findoptions.SetSkip(para.Size * (para.Page - 1))
  264. }
  265. if para.Sort != nil {
  266. findoptions.SetSort(para.Sort)
  267. }
  268. if len(para.Project) > 0 {
  269. prj := bson.M{}
  270. for _, v := range para.Project {
  271. prj[v] = 1
  272. }
  273. findoptions.SetProjection(prj)
  274. }
  275. filter := bson.M{}
  276. if len(para.Query) > 0 {
  277. for k, v := range para.Query {
  278. if value, ok := v.(string); ok {
  279. if len(value) > 0 {
  280. filter[k] = v
  281. continue
  282. }
  283. } else {
  284. filter[k] = v
  285. }
  286. }
  287. }
  288. cur, err := colls.Find(ctx.Ctx, filter, findoptions)
  289. if err != nil {
  290. return err
  291. }
  292. defer cur.Close(ctx.Ctx)
  293. err = cur.All(ctx.Ctx, out)
  294. return
  295. }
  296. func RepoDocArrayAppend(ctx *RepoSession, collectName string, idstr string, fieldpath string, arrayItem interface{}) (*mongo.UpdateResult, error) {
  297. colls := ctx.Client.GetCollection(collectName)
  298. arrayOp := bson.M{}
  299. arrayOp[fieldpath] = arrayItem
  300. update := bson.M{"$push": arrayOp}
  301. uid, _ := primitive.ObjectIDFromHex(idstr)
  302. return colls.UpdateByID(ctx.Ctx, uid, update)
  303. }
  304. // { _id: 4, "grades.grade": 85 },
  305. // { $set: { "grades.$.std" : 6 } }
  306. type ArrayOneUpdateOption struct {
  307. Query Map
  308. Set Map
  309. CollectName string
  310. Id string
  311. }
  312. // if len(scene.Stickers) > 0 {
  313. // optSet["scenes.$.stickers"] = scene.Stickers
  314. // }
  315. // option := &repo.ArrayOneUpdateOption{
  316. // CollectName: repo.CollectionDesigns,
  317. // Id: id,
  318. // Query: repo.Map{"scenes.id": scene.Id},
  319. // Set: optSet,
  320. // }
  321. func RepoDocArrayOneUpdate(ctx *RepoSession, options *ArrayOneUpdateOption) (*mongo.UpdateResult, error) {
  322. colls := ctx.Client.GetCollection(options.CollectName)
  323. docId, _ := primitive.ObjectIDFromHex(options.Id)
  324. query := bson.M{"_id": docId}
  325. if len(options.Query) > 0 {
  326. for k, v := range options.Query {
  327. query[k] = v
  328. }
  329. }
  330. setOp := bson.M{}
  331. for k, v := range options.Set {
  332. setOp[k] = v
  333. }
  334. update := bson.M{"$set": setOp}
  335. return colls.UpdateOne(ctx.Ctx, query, update)
  336. }
  337. type ArrayOneRemoveOption struct {
  338. ArrayQuery Map
  339. CollectName string
  340. Id string
  341. }
  342. // { $pull: { "items" : { id: 23 } } }
  343. func RepoDocArrayOneRemove(ctx *RepoSession, options *ArrayOneRemoveOption) (*mongo.UpdateResult, error) {
  344. colls := ctx.Client.GetCollection(options.CollectName)
  345. docId, _ := primitive.ObjectIDFromHex(options.Id)
  346. query := bson.M{"_id": docId}
  347. arrayQuery := bson.M{}
  348. if len(options.ArrayQuery) > 0 {
  349. for k, v := range options.ArrayQuery {
  350. arrayQuery[k] = v
  351. }
  352. }
  353. update := bson.M{"$pull": arrayQuery}
  354. return colls.UpdateOne(ctx.Ctx, query, update)
  355. }
  356. type ArrayOneSearchOption struct {
  357. ArrayQuery Map
  358. CollectName string
  359. Id string
  360. Field string
  361. }
  362. func RepoDocArraySearch(ctx *RepoSession, options *ArrayOneSearchOption, entity interface{}) error {
  363. colls := ctx.Client.GetCollection(options.CollectName)
  364. docId, _ := primitive.ObjectIDFromHex(options.Id)
  365. match := []bson.E{}
  366. match = append(match, bson.E{"_id", docId})
  367. matchStage := bson.D{
  368. {"$match", match},
  369. }
  370. unwindStage := bson.D{
  371. {"$unwind", fmt.Sprintf("%s%s", "$", options.Field)},
  372. }
  373. pipe := mongo.Pipeline{matchStage, unwindStage}
  374. if len(options.ArrayQuery) > 0 {
  375. match2 := []bson.E{}
  376. for k, v := range options.ArrayQuery {
  377. match2 = append(match2, bson.E{k, v})
  378. }
  379. match2Stage := bson.D{
  380. {"$match", match2},
  381. }
  382. pipe = append(pipe, match2Stage)
  383. }
  384. curr, err := colls.Aggregate(ctx.Ctx, pipe)
  385. if err != nil {
  386. return err
  387. }
  388. defer curr.Close(ctx.Ctx)
  389. if curr.Next(ctx.Ctx) {
  390. err = curr.Decode(entity)
  391. if err != nil {
  392. return err
  393. }
  394. return nil
  395. }
  396. return nil
  397. }
  398. type DocsSearchOptions struct {
  399. CollectName string
  400. Query map[string]interface{}
  401. Project []string
  402. Sort interface{} //bson.D{ bson.E{"update_time", -1}, bson.E{"goods_id", -1},}
  403. }
  404. func RepoSeachDocsMap(ctx *RepoSession, param *DocsSearchOptions) (ok bool, list []map[string]interface{}) {
  405. colls := ctx.Client.GetCollection(param.CollectName)
  406. findoptions := &options.FindOptions{}
  407. if len(param.Project) > 0 {
  408. prj := bson.M{}
  409. for _, v := range param.Project {
  410. prj[v] = 1
  411. }
  412. findoptions.SetProjection(prj)
  413. }
  414. if param.Sort != nil {
  415. findoptions.SetSort(param.Sort)
  416. }
  417. filter := bson.M{}
  418. if len(param.Query) > 0 {
  419. for k, v := range param.Query {
  420. if value, ok := v.(string); ok {
  421. if len(value) > 0 {
  422. filter[k] = v
  423. continue
  424. }
  425. } else {
  426. filter[k] = v
  427. }
  428. }
  429. }
  430. cur, err := colls.Find(ctx.Ctx, filter, findoptions)
  431. if err != nil {
  432. ok = false
  433. return
  434. }
  435. defer cur.Close(ctx.Ctx)
  436. listRes := []map[string]interface{}{}
  437. err = cur.All(ctx.Ctx, &listRes)
  438. if err != nil {
  439. log.Error(err)
  440. ok = false
  441. return
  442. }
  443. list = listRes
  444. ok = true
  445. return
  446. }
  447. type DbDocsSearchOptions struct {
  448. Db string
  449. CollectName string
  450. Query map[string]interface{}
  451. Project []string
  452. Sort interface{} //bson.D{ bson.E{"update_time", -1}, bson.E{"goods_id", -1},}
  453. }
  454. func DbRepoSeachDocsMap(ctx *RepoSession, param *DbDocsSearchOptions) (ok bool, list []map[string]interface{}) {
  455. colls := ctx.Client.GetDbCollection(param.Db, param.CollectName)
  456. findoptions := &options.FindOptions{}
  457. if len(param.Project) > 0 {
  458. prj := bson.M{}
  459. for _, v := range param.Project {
  460. prj[v] = 1
  461. }
  462. findoptions.SetProjection(prj)
  463. }
  464. if param.Sort != nil {
  465. findoptions.SetSort(param.Sort)
  466. }
  467. filter := bson.M{}
  468. if len(param.Query) > 0 {
  469. for k, v := range param.Query {
  470. if value, ok := v.(string); ok {
  471. if len(value) > 0 {
  472. filter[k] = v
  473. continue
  474. }
  475. } else {
  476. filter[k] = v
  477. }
  478. }
  479. }
  480. cur, err := colls.Find(ctx.Ctx, filter, findoptions)
  481. if err != nil {
  482. ok = false
  483. return
  484. }
  485. defer cur.Close(ctx.Ctx)
  486. listRes := []map[string]interface{}{}
  487. err = cur.All(ctx.Ctx, &listRes)
  488. if err != nil {
  489. log.Error(err)
  490. ok = false
  491. return
  492. }
  493. list = listRes
  494. ok = true
  495. return
  496. }