repo.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  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. if len(param.Sort) > 0 {
  187. opt.Sort = param.Sort
  188. }
  189. filter := bson.M{}
  190. if len(param.Query) > 0 {
  191. for k, v := range param.Query {
  192. if k == "_id" {
  193. if uid, ok := v.(string); ok {
  194. docId, _ := primitive.ObjectIDFromHex(uid)
  195. filter["_id"] = docId
  196. continue
  197. }
  198. }
  199. filter[k] = v
  200. }
  201. }
  202. ok = true
  203. err := colls.FindOne(ctx.Ctx, filter, opt).Decode(ret)
  204. if err == mongo.ErrNoDocuments {
  205. ok = false
  206. }
  207. if err != nil {
  208. ok = false
  209. }
  210. return ok, ret
  211. }
  212. // PageSearch 单表分页查询
  213. func RepoPageSearch(ctx *RepoSession, para *PageSearchOptions) (out *PageResult, err error) {
  214. var colls *mongo.Collection
  215. if len(para.Db) > 0 {
  216. colls = ctx.Client.GetDbCollection(para.Db, para.CollectName)
  217. } else {
  218. colls = ctx.Client.GetCollection(para.CollectName)
  219. }
  220. findoptions := &options.FindOptions{}
  221. if para.Size > 0 {
  222. findoptions.SetLimit(para.Size)
  223. findoptions.SetSkip(para.Size * (para.Page - 1))
  224. }
  225. if para.Sort != nil {
  226. findoptions.SetSort(para.Sort)
  227. }
  228. if len(para.Project) > 0 {
  229. prj := bson.M{}
  230. for _, v := range para.Project {
  231. prj[v] = 1
  232. }
  233. findoptions.SetProjection(prj)
  234. }
  235. filter := bson.M{}
  236. if len(para.Query) > 0 {
  237. for k, v := range para.Query {
  238. if value, ok := v.(string); ok {
  239. if len(value) > 0 {
  240. filter[k] = v
  241. continue
  242. }
  243. } else if v != nil {
  244. filter[k] = v
  245. }
  246. }
  247. }
  248. cur, err := colls.Find(ctx.Ctx, filter, findoptions)
  249. out = &PageResult{
  250. List: []map[string]interface{}{},
  251. Total: 0,
  252. Page: para.Page,
  253. Size: para.Size,
  254. }
  255. if err != nil {
  256. return out, err
  257. }
  258. defer cur.Close(ctx.Ctx)
  259. err = cur.All(ctx.Ctx, &out.List)
  260. out.Total, _ = colls.CountDocuments(ctx.Ctx, filter)
  261. return
  262. }
  263. func RepoDbCountDoc(ctx *RepoSession, db string, collectionName string, Query Map) (int64, error) {
  264. colls := ctx.Client.GetDbCollection(db, collectionName)
  265. filter := bson.M{}
  266. if len(Query) > 0 {
  267. for k, v := range Query {
  268. if value, ok := v.(string); ok {
  269. if len(value) > 0 {
  270. filter[k] = v
  271. continue
  272. }
  273. } else {
  274. filter[k] = v
  275. }
  276. }
  277. }
  278. return colls.CountDocuments(ctx.Ctx, filter)
  279. }
  280. func RepoCountDoc(ctx *RepoSession, collectionName string, Query Map) (int64, error) {
  281. colls := ctx.Client.GetCollection(collectionName)
  282. filter := bson.M{}
  283. if len(Query) > 0 {
  284. for k, v := range Query {
  285. if value, ok := v.(string); ok {
  286. if len(value) > 0 {
  287. filter[k] = v
  288. continue
  289. }
  290. } else {
  291. filter[k] = v
  292. }
  293. }
  294. }
  295. return colls.CountDocuments(ctx.Ctx, filter)
  296. }
  297. // PageSearch 单表分页查询
  298. func RepoDocsSearch(ctx *RepoSession, para *PageSearchOptions, out interface{}) (err error) {
  299. colls := ctx.Client.GetCollection(para.CollectName)
  300. if len(para.Db) > 0 {
  301. colls = ctx.Client.GetDbCollection(para.Db, para.CollectName)
  302. }
  303. findoptions := &options.FindOptions{}
  304. if para.Size > 0 {
  305. findoptions.SetLimit(para.Size)
  306. findoptions.SetSkip(para.Size * (para.Page - 1))
  307. }
  308. if para.Sort != nil {
  309. findoptions.SetSort(para.Sort)
  310. }
  311. if len(para.Project) > 0 {
  312. prj := bson.M{}
  313. for _, v := range para.Project {
  314. prj[v] = 1
  315. }
  316. findoptions.SetProjection(prj)
  317. }
  318. filter := bson.M{}
  319. if len(para.Query) > 0 {
  320. for k, v := range para.Query {
  321. if value, ok := v.(string); ok {
  322. if len(value) > 0 {
  323. filter[k] = v
  324. continue
  325. }
  326. } else {
  327. filter[k] = v
  328. }
  329. }
  330. }
  331. cur, err := colls.Find(ctx.Ctx, filter, findoptions)
  332. if err != nil {
  333. return err
  334. }
  335. defer cur.Close(ctx.Ctx)
  336. err = cur.All(ctx.Ctx, out)
  337. return
  338. }
  339. func RepoDocArrayAppend(ctx *RepoSession, collectName string, idstr string, fieldpath string, arrayItem interface{}) (*mongo.UpdateResult, error) {
  340. colls := ctx.Client.GetCollection(collectName)
  341. arrayOp := bson.M{}
  342. arrayOp[fieldpath] = arrayItem
  343. update := bson.M{"$push": arrayOp}
  344. uid, _ := primitive.ObjectIDFromHex(idstr)
  345. return colls.UpdateByID(ctx.Ctx, uid, update)
  346. }
  347. // { _id: 4, "grades.grade": 85 },
  348. // { $set: { "grades.$.std" : 6 } }
  349. type ArrayOneUpdateOption struct {
  350. Query Map
  351. Set Map
  352. CollectName string
  353. Id string
  354. }
  355. // if len(scene.Stickers) > 0 {
  356. // optSet["scenes.$.stickers"] = scene.Stickers
  357. // }
  358. // option := &repo.ArrayOneUpdateOption{
  359. // CollectName: repo.CollectionDesigns,
  360. // Id: id,
  361. // Query: repo.Map{"scenes.id": scene.Id},
  362. // Set: optSet,
  363. // }
  364. func RepoDocArrayOneUpdate(ctx *RepoSession, options *ArrayOneUpdateOption) (*mongo.UpdateResult, error) {
  365. colls := ctx.Client.GetCollection(options.CollectName)
  366. docId, _ := primitive.ObjectIDFromHex(options.Id)
  367. query := bson.M{"_id": docId}
  368. if len(options.Query) > 0 {
  369. for k, v := range options.Query {
  370. query[k] = v
  371. }
  372. }
  373. setOp := bson.M{}
  374. for k, v := range options.Set {
  375. setOp[k] = v
  376. }
  377. update := bson.M{"$set": setOp}
  378. return colls.UpdateOne(ctx.Ctx, query, update)
  379. }
  380. type ArrayOneRemoveOption struct {
  381. ArrayQuery Map
  382. CollectName string
  383. Id string
  384. }
  385. // { $pull: { "items" : { id: 23 } } }
  386. func RepoDocArrayOneRemove(ctx *RepoSession, options *ArrayOneRemoveOption) (*mongo.UpdateResult, error) {
  387. colls := ctx.Client.GetCollection(options.CollectName)
  388. docId, _ := primitive.ObjectIDFromHex(options.Id)
  389. query := bson.M{"_id": docId}
  390. arrayQuery := bson.M{}
  391. if len(options.ArrayQuery) > 0 {
  392. for k, v := range options.ArrayQuery {
  393. arrayQuery[k] = v
  394. }
  395. }
  396. update := bson.M{"$pull": arrayQuery}
  397. return colls.UpdateOne(ctx.Ctx, query, update)
  398. }
  399. type ArrayOneSearchOption struct {
  400. ArrayQuery Map
  401. CollectName string
  402. Id string
  403. Field string
  404. }
  405. func RepoDocArraySearch(ctx *RepoSession, options *ArrayOneSearchOption, entity interface{}) error {
  406. colls := ctx.Client.GetCollection(options.CollectName)
  407. docId, _ := primitive.ObjectIDFromHex(options.Id)
  408. match := []bson.E{}
  409. match = append(match, bson.E{"_id", docId})
  410. matchStage := bson.D{
  411. {"$match", match},
  412. }
  413. unwindStage := bson.D{
  414. {"$unwind", fmt.Sprintf("%s%s", "$", options.Field)},
  415. }
  416. pipe := mongo.Pipeline{matchStage, unwindStage}
  417. if len(options.ArrayQuery) > 0 {
  418. match2 := []bson.E{}
  419. for k, v := range options.ArrayQuery {
  420. match2 = append(match2, bson.E{k, v})
  421. }
  422. match2Stage := bson.D{
  423. {"$match", match2},
  424. }
  425. pipe = append(pipe, match2Stage)
  426. }
  427. curr, err := colls.Aggregate(ctx.Ctx, pipe)
  428. if err != nil {
  429. return err
  430. }
  431. defer curr.Close(ctx.Ctx)
  432. if curr.Next(ctx.Ctx) {
  433. err = curr.Decode(entity)
  434. if err != nil {
  435. return err
  436. }
  437. return nil
  438. }
  439. return nil
  440. }
  441. type DocsSearchOptions struct {
  442. CollectName string
  443. Query map[string]interface{}
  444. Project []string
  445. Sort interface{} //bson.D{ bson.E{"update_time", -1}, bson.E{"goods_id", -1},}
  446. }
  447. func RepoSeachDocsMap(ctx *RepoSession, param *DocsSearchOptions) (ok bool, list []map[string]interface{}) {
  448. colls := ctx.Client.GetCollection(param.CollectName)
  449. findoptions := &options.FindOptions{}
  450. if len(param.Project) > 0 {
  451. prj := bson.M{}
  452. for _, v := range param.Project {
  453. prj[v] = 1
  454. }
  455. findoptions.SetProjection(prj)
  456. }
  457. if param.Sort != nil {
  458. findoptions.SetSort(param.Sort)
  459. }
  460. filter := bson.M{}
  461. if len(param.Query) > 0 {
  462. for k, v := range param.Query {
  463. if value, ok := v.(string); ok {
  464. if len(value) > 0 {
  465. filter[k] = v
  466. continue
  467. }
  468. } else {
  469. filter[k] = v
  470. }
  471. }
  472. }
  473. cur, err := colls.Find(ctx.Ctx, filter, findoptions)
  474. if err != nil {
  475. ok = false
  476. return
  477. }
  478. defer cur.Close(ctx.Ctx)
  479. listRes := []map[string]interface{}{}
  480. err = cur.All(ctx.Ctx, &listRes)
  481. if err != nil {
  482. log.Error(err)
  483. ok = false
  484. return
  485. }
  486. list = listRes
  487. ok = true
  488. return
  489. }
  490. type DbDocsSearchOptions struct {
  491. Db string
  492. CollectName string
  493. Query map[string]interface{}
  494. Project []string
  495. Sort interface{} //bson.D{ bson.E{"update_time", -1}, bson.E{"goods_id", -1},}
  496. }
  497. func DbRepoSeachDocsMap(ctx *RepoSession, param *DbDocsSearchOptions) (ok bool, list []map[string]interface{}) {
  498. colls := ctx.Client.GetDbCollection(param.Db, param.CollectName)
  499. findoptions := &options.FindOptions{}
  500. if len(param.Project) > 0 {
  501. prj := bson.M{}
  502. for _, v := range param.Project {
  503. prj[v] = 1
  504. }
  505. findoptions.SetProjection(prj)
  506. }
  507. if param.Sort != nil {
  508. findoptions.SetSort(param.Sort)
  509. }
  510. filter := bson.M{}
  511. if len(param.Query) > 0 {
  512. for k, v := range param.Query {
  513. if value, ok := v.(string); ok {
  514. if len(value) > 0 {
  515. filter[k] = v
  516. continue
  517. }
  518. } else {
  519. filter[k] = v
  520. }
  521. }
  522. }
  523. cur, err := colls.Find(ctx.Ctx, filter, findoptions)
  524. if err != nil {
  525. ok = false
  526. return
  527. }
  528. defer cur.Close(ctx.Ctx)
  529. listRes := []map[string]interface{}{}
  530. err = cur.All(ctx.Ctx, &listRes)
  531. if err != nil {
  532. log.Error(err)
  533. ok = false
  534. return
  535. }
  536. list = listRes
  537. ok = true
  538. return
  539. }