repo.go 14 KB

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