repo.go 15 KB

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