经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » MongoDB » 查看文章
记一次Mongodb数据库查询之包含所有指定元素的数组或者都在指定元素的数组中 - du-blog
来源:cnblogs  作者:du-blog  时间:2021/12/24 8:57:56  对本文有异议

  这里记录一个查询需求:数据库中字段的值(数组类型)都在指定的数组中。举例说一下实际场景,数据库中一个字段存储用户“可以使用的编程语言”,一般都会是多个,所以该字段是数组格式。现在要查询的是:会c#、javascript或者只会c#或者只会javascript的用户,翻译一下就是数据库中字段的值是子集而给定的数组是全集。这种查询需要在mongodb没有找到特定的查询操作符,这篇笔记主要解决这个问题,顺便介绍一下"$all"运算符。"$all"查询的是数据库字段的值包含所有指定元素的数组,也就是数据库中字段的值是全集而给定的数组是子集,和前面提到的需求相反。

  为了演示上述的两种查询需求,先造一些测试数据,下面是表结构:

编程语言调查表(FormId: 507048044944694000, FormVersion: 507048044944694001

唯一标识

中文描述

控件类型

是否必填

表单项的其他配置(在表单设计时配置,文本框长度、时间格式等)

1572493554001

用户

选择人员控件

1572493554002

可以使用的编程语言

复选框

1572493554003

最喜欢的编程语言

文本框

1572493554004

工作地点

文本框

1572493554005

工作年限

数值输入框

1572493554006

备注

多行文本框

  下面是造数据的语句

  1. var GV_TableName = "FormInstace",
  2. GV_FormId = "507048044944694000",
  3. GV_FormVersion = "507048044944694001",
  4. GV_CreateUserIds = ["user10000", "user10001", "user10002", "user10003", "user10004", "user10005", "user10006", "user10007", "user10008", "user10009"];
  5. var GV_LangObj = {
  6. 1: {
  7. id: "1",
  8. text: "C#"
  9. },
  10. 2: {
  11. id: "2",
  12. text: "JavaScript"
  13. },
  14. 3: {
  15. id: "3",
  16. text: "HTML"
  17. },
  18. 4: {
  19. id: "4",
  20. text: "CSS"
  21. },
  22. 5: {
  23. id: "5",
  24. text: "Go"
  25. },
  26. 6: {
  27. id: "6",
  28. text: "Rust"
  29. }
  30. };
  31. var GV_Name2Id = {
  32. "userName": "1572493554001",
  33. "lang": "1572493554002",
  34. "favLang": "1572493554003",
  35. "workPlace": "1572493554004",
  36. "workYears": "1572493554005",
  37. "remarks": "1572493554006",
  38. };
  39. var getGUID = function () {
  40. return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
  41. var r = Math.random() * 16 | 0,
  42. v = c == 'x' ? r : (r & 0x3 | 0x8);
  43. return v.toString(16).toUpperCase();
  44. });
  45. }
  46. var getFormInstanceOtherAttrs = function (formId, formVersion) {
  47. var tempCreateUserIdIndex = Math.floor(Math.random() * GV_CreateUserIds.length),
  48. tempCreateDate = ISODate();
  49. return {
  50. _id: getGUID(),
  51. ExtendData: {},
  52. CreateUserId: GV_CreateUserIds[tempCreateUserIdIndex],
  53. CreateUserName: GV_CreateUserIds[tempCreateUserIdIndex],
  54. CreateDate: tempCreateDate,
  55. LastModifyDate: tempCreateDate,
  56. FormId: GV_FormId,
  57. FormVersion: GV_FormVersion
  58. };
  59. };
  60. var assembleFormInstance = function (formItemsAttr) {
  61. return Object.assign(formItemsAttr, getFormInstanceOtherAttrs());
  62. }
  63. //************************************************************************************************************************************************
  64.  
  65. // 批量插入数据
  66. db[GV_TableName].insertMany([
  67. assembleFormInstance({
  68. FormItems: [{
  69. key: GV_Name2Id.userName,
  70. value: "u1"
  71. }, {
  72. key: GV_Name2Id.lang,
  73. value: [GV_LangObj['1'], GV_LangObj['2'], GV_LangObj['3'], GV_LangObj['4']]
  74. }, {
  75. key: GV_Name2Id.favLang,
  76. value: [GV_LangObj['1']]
  77. }, {
  78. key: GV_Name2Id.workPlace,
  79. value: "北京"
  80. }, {
  81. key: GV_Name2Id.workYears,
  82. value: 1
  83. }, {
  84. key: GV_Name2Id.remarks,
  85. value: "随便写点什么"
  86. }
  87. ]
  88. }),
  89. assembleFormInstance({
  90. FormItems: [{
  91. key: GV_Name2Id.userName,
  92. value: "u2"
  93. }, {
  94. key: GV_Name2Id.lang,
  95. value: [GV_LangObj['1'], GV_LangObj['2'], GV_LangObj['6']]
  96. }, {
  97. key: GV_Name2Id.favLang,
  98. value: [GV_LangObj['6']]
  99. }, {
  100. key: GV_Name2Id.workPlace,
  101. value: "天津"
  102. }, {
  103. key: GV_Name2Id.workYears,
  104. value: 2
  105. }, {
  106. key: GV_Name2Id.remarks,
  107. value: "随便写点什么"
  108. }
  109. ]
  110. }),
  111. assembleFormInstance({
  112. FormItems: [{
  113. key: GV_Name2Id.userName,
  114. value: "u3"
  115. }, {
  116. key: GV_Name2Id.lang,
  117. value: [GV_LangObj['1'], GV_LangObj['2']]
  118. }, {
  119. key: GV_Name2Id.favLang,
  120. value: [GV_LangObj['1']]
  121. }, {
  122. key: GV_Name2Id.workPlace,
  123. value: "石家庄"
  124. }, {
  125. key: GV_Name2Id.workYears,
  126. value: 3
  127. }, {
  128. key: GV_Name2Id.remarks,
  129. value: "随便写点什么"
  130. }
  131. ]
  132. }),
  133. assembleFormInstance({
  134. FormItems: [{
  135. key: GV_Name2Id.userName,
  136. value: "u4"
  137. }, {
  138. key: GV_Name2Id.lang,
  139. value: [GV_LangObj['1'], GV_LangObj['5']]
  140. }, {
  141. key: GV_Name2Id.favLang,
  142. value: [GV_LangObj['5']]
  143. }, {
  144. key: GV_Name2Id.workPlace,
  145. value: "上海"
  146. }, {
  147. key: GV_Name2Id.workYears,
  148. value: 4
  149. }, {
  150. key: GV_Name2Id.remarks,
  151. value: "随便写点什么"
  152. }
  153. ]
  154. }),
  155. assembleFormInstance({
  156. FormItems: [{
  157. key: GV_Name2Id.userName,
  158. value: "u5"
  159. }, {
  160. key: GV_Name2Id.lang,
  161. value: [GV_LangObj['1']]
  162. }, {
  163. key: GV_Name2Id.favLang,
  164. value: [GV_LangObj['1']]
  165. }, {
  166. key: GV_Name2Id.workPlace,
  167. value: "广州"
  168. }, {
  169. key: GV_Name2Id.workYears,
  170. value: 5
  171. }, {
  172. key: GV_Name2Id.remarks,
  173. value: "随便写点什么"
  174. }
  175. ]
  176. }),
  177. assembleFormInstance({
  178. FormItems: [{
  179. key: GV_Name2Id.userName,
  180. value: "u6"
  181. }, {
  182. key: GV_Name2Id.lang,
  183. value: [GV_LangObj['2']]
  184. }, {
  185. key: GV_Name2Id.favLang,
  186. value: [GV_LangObj['2']]
  187. }, {
  188. key: GV_Name2Id.workPlace,
  189. value: "深圳"
  190. }, {
  191. key: GV_Name2Id.workYears,
  192. value: 6
  193. }, {
  194. key: GV_Name2Id.remarks,
  195. value: "随便写点什么"
  196. }
  197. ]
  198. }),
  199. assembleFormInstance({
  200. FormItems: [{
  201. key: GV_Name2Id.userName,
  202. value: "u7"
  203. }, {
  204. key: GV_Name2Id.lang,
  205. value: []
  206. }, {
  207. key: GV_Name2Id.favLang,
  208. value: []
  209. }, {
  210. key: GV_Name2Id.workPlace,
  211. value: "成都"
  212. }, {
  213. key: GV_Name2Id.workYears,
  214. value: 7
  215. }, {
  216. key: GV_Name2Id.remarks,
  217. value: "随便写点什么"
  218. }
  219. ]
  220. }),
  221. assembleFormInstance({
  222. FormItems: [{
  223. key: GV_Name2Id.userName,
  224. value: "u8"
  225. }, {
  226. key: GV_Name2Id.lang,
  227. value: [GV_LangObj['5'], GV_LangObj['6']]
  228. }, {
  229. key: GV_Name2Id.favLang,
  230. value: [GV_LangObj['5']]
  231. }, {
  232. key: GV_Name2Id.workPlace,
  233. value: "重庆"
  234. }, {
  235. key: GV_Name2Id.workYears,
  236. value: 8
  237. }, {
  238. key: GV_Name2Id.remarks,
  239. value: "随便写点什么"
  240. }
  241. ]
  242. }),
  243. ]);
View Code

  看一下插入的数据:

   这里数据结构和之前表单生成器(Form Builder)之表单数据存储结构mongodb篇文章中介绍的一样。为了方便查看,将“可以使用的编程语言”字段从“FormItems”数组中拿出来并放在最外层,下面是语句

  1. // 通用聚合管道(将“编程语言”表单项从"FormItems"中拷贝一份放到最外层,方便查看)
  2. var showLangItemPrePipeline = [{
  3. $addFields: {
  4. FormItemObj: {
  5. $arrayToObject: {
  6. $map: {
  7. input: "$FormItems",
  8. as: "field",
  9. in: [
  10. "$$field.key",
  11. "$$field.value"
  12. ]
  13. }
  14. }
  15. }
  16. }
  17. }, {
  18. $addFields: {
  19. "LangFormItem": "$FormItemObj.1572493554002",
  20. }
  21. }, {
  22. $addFields: {
  23. "1572493554002": {
  24. $reduce: {
  25. input: "$LangFormItem",
  26. initialValue: "",
  27. in: {
  28. $concat: ["$$value", "$$this.text", ","]
  29. }
  30. }
  31. },
  32. }
  33. }, {
  34. $project: {
  35. 'FormItemObj': 0,
  36. 'LangFormItem': 0
  37. }
  38. }
  39. ];
  40. // 1、查询:展示一下插入的示例数据
  41. db.getCollection("FormInstace").aggregate(showLangItemPrePipeline);

  下面看一下查询效果:

   说明:从制造假数据的语句中你可以看到“1572493554002”字段是数组类型并且每一项都是一个对象,上图中将数组拼接成了字符串,方便查看。

  先来看一下数据库中字段的值都在指定元素的数组中的查询语句:

  1. // 通用聚合管道(将“编程语言”表单项从"FormItems"中拷贝一份放到最外层,方便查看)
  2. var showLangItemPrePipeline = [{
  3. $addFields: {
  4. FormItemObj: {
  5. $arrayToObject: {
  6. $map: {
  7. input: "$FormItems",
  8. as: "field",
  9. in: [
  10. "$$field.key",
  11. "$$field.value"
  12. ]
  13. }
  14. }
  15. }
  16. }
  17. }, {
  18. $addFields: {
  19. "LangFormItem": "$FormItemObj.1572493554002",
  20. }
  21. }, {
  22. $addFields: {
  23. "1572493554002": {
  24. $reduce: {
  25. input: "$LangFormItem",
  26. initialValue: "",
  27. in: {
  28. $concat: ["$$value", "$$this.text", ","]
  29. }
  30. }
  31. },
  32. }
  33. }, {
  34. $project: {
  35. 'FormItemObj': 0,
  36. 'LangFormItem': 0
  37. }
  38. }
  39. ];
  40. db.getCollection("FormInstace").aggregate(showLangItemPrePipeline.concat([{
  41. "$match": {
  42. "FormId": "507048044944694000",
  43. "FormItems": {
  44. "$elemMatch": {
  45. "key": "1572493554002",
  46. "value.0": {
  47. '$exists': true
  48. },
  49. "value": {
  50. "$not": {
  51. "$elemMatch": {
  52. "text": {
  53. "$nin": ["C#", "JavaScript"]
  54. }
  55. }
  56. }
  57. }
  58. }
  59. }
  60. }
  61. }
  62. ]))

  来一张截图,看一下查询结果:

   注意:这里语句中还用到了“$exists”运算符,如果不添加这个会将数组长度为0的查出来。参考链接

  在看一下“$all”查询,数据库字段的值包含所有指定元素的数组:

  1. // 通用聚合管道(将“编程语言”表单项从"FormItems"中拷贝一份放到最外层,方便查看)
  2. var showLangItemPrePipeline = [{
  3. $addFields: {
  4. FormItemObj: {
  5. $arrayToObject: {
  6. $map: {
  7. input: "$FormItems",
  8. as: "field",
  9. in: [
  10. "$$field.key",
  11. "$$field.value"
  12. ]
  13. }
  14. }
  15. }
  16. }
  17. }, {
  18. $addFields: {
  19. "LangFormItem": "$FormItemObj.1572493554002",
  20. }
  21. }, {
  22. $addFields: {
  23. "1572493554002": {
  24. $reduce: {
  25. input: "$LangFormItem",
  26. initialValue: "",
  27. in: {
  28. $concat: ["$$value", "$$this.text", ","]
  29. }
  30. }
  31. },
  32. }
  33. }, {
  34. $project: {
  35. 'FormItemObj': 0,
  36. 'LangFormItem': 0
  37. }
  38. }
  39. ];
  40. db.getCollection('FormInstace').aggregate(showLangItemPrePipeline.concat([{
  41. "$match": {
  42. "FormId": "507048044944694000",
  43. "FormItems": {
  44. "$elemMatch": {
  45. "key": "1572493554002",
  46. "value.text": {
  47. "$all": ["C#", "JavaScript"]
  48. }
  49. }
  50. }
  51. }
  52. }
  53. ]))

  来一张截图,看一下查询结果:

   这里在顺便记录一下在mongodb中数值转字符串,高版本有“$toString”操作符(版本4.0)、“$convert”操作符(版本4.0)……但是低版本的该如何处理,参考链接。这个例子比较简单,就不写制造数据的语句了,直接来查询语句:

  1. db.getCollection('test001').aggregate([
  2. {
  3. $addFields: {
  4. "ageStr": { $substr: [ "$num", 0, -1 ] }
  5. }
  6. }
  7. ])

  来一张截图,看一下查询结果:

原文链接:http://www.cnblogs.com/du-blog/p/15722774.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号