Mongodb 多文档聚合操作处理方法三(聚合管道)

聚合

聚合操作处理多个文档并返回计算结果。您可以使用聚合操作来:

  • 将多个文档中的值分组在一起。

  • 对分组数据执行操作以返回单个结果。

  • 分析数据随时间的变化。

要执行聚合操作,您可以使用:

  • 聚合管道

  • 单一目的聚合方法

  • Map-reduce 函数

聚合管道

聚合管道由一个或多个处理文档的阶段组成:

  • 除$out、$merge、$geoNear和$changeStream阶段之外的所有阶段都可以在管道中出现多次

  • 每个阶段都对输入文档执行操作。例如,阶段可以过滤文档、对文档进行分组以及计算值。

  • 从一个阶段输出的文档将输入到下一阶段。

  • 聚合管道可以返回文档组的结果。例如,返回总计、平均值、最大值和最小值。

聚合阶段

在db.collection.aggregate()方法和db.aggregate()方法中,管道阶段出现在数组中。文档按顺序经过这些阶段。

db.collection.aggregate( [ { <stage> }, ... ] )

常见几种阶段:

阶段描述
$group按指定的标识符表达式对输入文档进行分组,并在指定的情况下对每个组应用累加器表达式。消耗所有输入文档,并为每个不同的组输出一个文档。输出文档只包含标识符字段,如果指定的话,还包含累积字段。
$limit将未修改的前n 个文档传递到管道,其中n是指定的限制。对于每个输入文档,输出一个文档(前n 个文档)或零个文档(前n 个文档之后)。
$match过滤文档流以仅允许匹配的文档未经修改地传递到下一个管道阶段。 $match使用标准 MongoDB 查询。对于每个输入文档,输出一个文档(匹配)或零个文档(不匹配)。
$merge将聚合管道的结果文档写入集合。该阶段可以将结果合并(插入新文档、合并文档、替换文档、保留现有文档、操作失败、使用自定义更新管道处理文档)结果到输出集合中。要使用该$merge阶段,它必须是管道中的最后一个阶段。
$out将聚合管道的结果文档写入集合。要使用该$out阶段,它必须是管道中的最后一个阶段。
$project重塑流中的每个文档,例如通过添加新字段或删除现有字段。对于每个输入文档,输出一个文档。
$sort按指定的排序键对文档流重新排序。仅顺序发生变化;文件保持不变。对于每个输入文档,输出一个文档。
$unwind从输入文档解构数组字段以输出每个元素的文档。每个输出文档都用一个元素值替换数组。对于每个输入文档,输出n个文档,其中n是数组元素的数量,对于空数组可以为零。

测试数据如下:

sit_rs1:PRIMARY> db.orders.find() 
{ "_id" : 4, "cust_id" : "B", "ord_date" : ISODate("2023-06-18T00:00:00Z"), "price" : 26, "items" : [ { "sku" : "apple", "qty" : 10, "price" : 2.5 } ], "status" : "1" }
{ "_id" : 6, "cust_id" : "C", "ord_date" : ISODate("2023-06-19T00:00:00Z"), "price" : 38, "items" : [ { "sku" : "carrots", "qty" : 10, "price" : 1 }, { "sku" : "apples", "qty" : 10, "price" : 2.5 } ], "status" : "1" }
{ "_id" : 1, "cust_id" : "A", "ord_date" : ISODate("2023-06-01T00:00:00Z"), "price" : 15, "items" : [ { "sku" : "apple", "qty" : 5, "price" : 2.5 }, { "sku" : "apples", "qty" : 5, "price" : 2.5 } ], "status" : "1" }
{ "_id" : 2, "cust_id" : "A", "ord_date" : ISODate("2023-06-08T00:00:00Z"), "price" : 60, "items" : [ { "sku" : "apple", "qty" : 8, "price" : 2.5 }, { "sku" : "banana", "qty" : 5, "price" : 10 } ], "status" : "1" }
{ "_id" : 9, "cust_id" : "D", "ord_date" : ISODate("2023-06-20T00:00:00Z"), "price" : 51, "items" : [ { "sku" : "carrots", "qty" : 5, "price" : 1 }, { "sku" : "apples", "qty" : 10, "price" : 2.5 }, { "sku" : "apple", "qty" : 10, "price" : 2.5 } ], "status" : "1" }
{ "_id" : 3, "cust_id" : "B", "ord_date" : ISODate("2023-06-08T00:00:00Z"), "price" : 55, "items" : [ { "sku" : "apple", "qty" : 10, "price" : 2.5 }, { "sku" : "pears", "qty" : 10, "price" : 2.5 } ], "status" : "1" }
{ "_id" : 5, "cust_id" : "B", "ord_date" : ISODate("2023-06-19T00:00:00Z"), "price" : 40, "items" : [ { "sku" : "banana", "qty" : 5, "price" : 10 } ], "status" : "1" }
{ "_id" : 7, "cust_id" : "C", "ord_date" : ISODate("2023-06-20T00:00:00Z"), "price" : 21, "items" : [ { "sku" : "apple", "qty" : 10, "price" : 2.5 } ], "status" : "1" }
{ "_id" : 8, "cust_id" : "D", "ord_date" : ISODate("2023-06-20T00:00:00Z"), "price" : 76, "items" : [ { "sku" : "banana", "qty" : 5, "price" : 10 }, { "sku" : "apples", "qty" : 10, "price" : 2.5 } ], "status" : "1" }
{ "_id" : 10, "cust_id" : "D", "ord_date" : ISODate("2023-06-23T00:00:00Z"), "price" : 23, "items" : [ { "sku" : "apple", "qty" : 10, "price" : 2.5 } ], "status" : "1" }

示例一:

查询客户: “D” 的订单,按日期分组,返回每天的订单总价

$match 阶段:

  • 匹配 “cust_id” : “D” 的记录。
  • 将过滤后的文档输出到 group 阶段。

$group 阶段:

  • 输入的文档按 ord_date 进行分组。
  • 使用 $sum 运算符计算价格总和,并将结果存放聚合管道 sumPrice 字段中。
sit_rs1:PRIMARY> db.orders.aggregate( [
...    { $match: { "cust_id" : "D" } },
...    { $group: { _id: "$ord_date", sumPrice: { $sum: "$price" } } }
... ] )
{ "_id" : ISODate("2023-06-20T00:00:00Z"), "sumPrice" : 127 }
{ "_id" : ISODate("2023-06-23T00:00:00Z"), "sumPrice" : 23 }

示例二

按照客户进行分组,统计每个客户的订单总价,并总价降序排序。取前三名的客户,如下

$group 阶段:

  • 输入的文档按 cust_id进行分组。
  • 使用 $sum 运算符计算价格总和,并将结果存放聚合管道 sumPrice 字段中。

$sort 阶段:

  • 按 sumPrice 字段以相反的顺序对这些文档进行排序。

$limit 阶段:

  • 运算 $limit 仅包含前 3 个结果文档。
sit_rs1:PRIMARY> db.orders.aggregate(
...   [
...     { $group : { _id : "$cust_id" , sumPrice : { $sum : "$price" } } },
...     { $sort : { sumPrice : -1 } },
...     { $limit : 3 }
...   ]
... )
{ "_id" : "D", "sumPrice" : 150 }
{ "_id" : "B", "sumPrice" : 121 }
{ "_id" : "A", "sumPrice" : 75 }

示例三

按照客户进行分组,统计每个客户的订单总价,并输出到结果集合:agg_cust_id_1 ,如下

$group 阶段:

  • 输入的文档按 cust_id进行分组。
  • 使用 $sum 运算符计算价格总和,并将结果存放聚合管道 value字段中。

$out 阶段

  • 将输出写入集合 agg_cust_id_1
sit_rs1:PRIMARY> db.orders.aggregate([
...    { $group: { _id: "$cust_id", value: { $sum: "$price" } } },
...    { $out: "agg_cust_id_1" }
... ])# 查询  agg_cust_id_1  集合以验证结果:
sit_rs1:PRIMARY> db.agg_cust_id_1.find()
{ "_id" : "A", "value" : 75 }
{ "_id" : "D", "value" : 150 }
{ "_id" : "B", "value" : 121 }
{ "_id" : "C", "value" : 59 }sit_rs1:PRIMARY> db.orders.find({}, { "cust_id": 1, "price": 1})
{ "_id" : 4, "cust_id" : "B", "price" : 26 }
{ "_id" : 6, "cust_id" : "C", "price" : 38 }
{ "_id" : 1, "cust_id" : "A", "price" : 15 }
{ "_id" : 2, "cust_id" : "A", "price" : 60 }
{ "_id" : 9, "cust_id" : "D", "price" : 51 }
{ "_id" : 3, "cust_id" : "B", "price" : 55 }
{ "_id" : 5, "cust_id" : "B", "price" : 40 }
{ "_id" : 7, "cust_id" : "C", "price" : 21 }
{ "_id" : 8, "cust_id" : "D", "price" : 76 }
{ "_id" : 10, "cust_id" : "D", "price" : 23 }

示例四

计算某个SKU单品总共下了多少单,销售总数量,及平均每单数量是多少,如下:

首先查询日期大于等于 2023-03-01 的订单, 按数组 items 字段 分解文档(即如果数组包含N个元素,将分解为N个文档)。 再对 items.sku进行分组统计,并计算 qty 的数量总和。 orders_ids 把相同组的订单ID号添加到数组。

sit_rs1:PRIMARY> db.orders.aggregate( [
...    { $match: { ord_date: { $gte: new Date("2023-03-01") } } },
...    { $unwind: "$items" },
...    { $group: { _id: "$items.sku", qty: { $sum: "$items.qty" }, orders_ids: { $addToSet: "$_id" } }  },
...    { $project: { value: { count: { $size: "$orders_ids" }, qty: "$qty", avg: { $divide: [ "$qty", { $size: "$orders_ids" } ] } } } },
...    { $merge: { into: "agg_sku", on: "_id", whenMatched: "replace",  whenNotMatched: "insert" } }
... ] )# 查询  agg_sku  集合以验证结果: 
sit_rs1:PRIMARY> db.agg_sku.find()
{ "_id" : "apple", "value" : { "count" : 7, "qty" : 63, "avg" : 9 } }
{ "_id" : "banana", "value" : { "count" : 3, "qty" : 15, "avg" : 5 } }
{ "_id" : "apples", "value" : { "count" : 4, "qty" : 35, "avg" : 8.75 } }
{ "_id" : "carrots", "value" : { "count" : 2, "qty" : 15, "avg" : 7.5 } }
{ "_id" : "pears", "value" : { "count" : 1, "qty" : 10, "avg" : 10 } }

接下来,各阶段执行过程详细如下:

$match阶段

  • 该阶段仅选择那些大于或等于2023-03-01 的文档,输出如下:
sit_rs1:PRIMARY> db.orders.aggregate( [
...    { $match: { ord_date: { $gte: new Date("2023-03-01") } } }
... ] )
{ "_id" : 2, "cust_id" : "A", "ord_date" : ISODate("2023-06-08T00:00:00Z"), "price" : 60, "items" : [ { "sku" : "apple", "qty" : 8, "price" : 2.5 }, { "sku" : "banana", "qty" : 5, "price" : 10 } ], "status" : "1" }
{ "_id" : 3, "cust_id" : "B", "ord_date" : ISODate("2023-06-08T00:00:00Z"), "price" : 55, "items" : [ { "sku" : "apple", "qty" : 10, "price" : 2.5 }, { "sku" : "pears", "qty" : 10, "price" : 2.5 } ], "status" : "1" }
{ "_id" : 7, "cust_id" : "C", "ord_date" : ISODate("2023-06-20T00:00:00Z"), "price" : 21, "items" : [ { "sku" : "apple", "qty" : 10, "price" : 2.5 } ], "status" : "1" }
{ "_id" : 9, "cust_id" : "D", "ord_date" : ISODate("2023-06-20T00:00:00Z"), "price" : 51, "items" : [ { "sku" : "carrots", "qty" : 5, "price" : 1 }, { "sku" : "apples", "qty" : 10, "price" : 2.5 }, { "sku" : "apple", "qty" : 10, "price" : 2.5 } ], "status" : "1" }
{ "_id" : 1, "cust_id" : "A", "ord_date" : ISODate("2023-06-01T00:00:00Z"), "price" : 15, "items" : [ { "sku" : "apple", "qty" : 5, "price" : 2.5 }, { "sku" : "apples", "qty" : 5, "price" : 2.5 } ], "status" : "1" }
{ "_id" : 4, "cust_id" : "B", "ord_date" : ISODate("2023-06-18T00:00:00Z"), "price" : 26, "items" : [ { "sku" : "apple", "qty" : 10, "price" : 2.5 } ], "status" : "1" }
{ "_id" : 10, "cust_id" : "D", "ord_date" : ISODate("2023-06-23T00:00:00Z"), "price" : 23, "items" : [ { "sku" : "apple", "qty" : 10, "price" : 2.5 } ], "status" : "1" }
{ "_id" : 6, "cust_id" : "C", "ord_date" : ISODate("2023-06-19T00:00:00Z"), "price" : 38, "items" : [ { "sku" : "carrots", "qty" : 10, "price" : 1 }, { "sku" : "apples", "qty" : 10, "price" : 2.5 } ], "status" : "1" }
{ "_id" : 5, "cust_id" : "B", "ord_date" : ISODate("2023-06-19T00:00:00Z"), "price" : 40, "items" : [ { "sku" : "banana", "qty" : 5, "price" : 10 } ], "status" : "1" }
{ "_id" : 8, "cust_id" : "D", "ord_date" : ISODate("2023-06-20T00:00:00Z"), "price" : 76, "items" : [ { "sku" : "banana", "qty" : 5, "price" : 10 }, { "sku" : "apples", "qty" : 10, "price" : 2.5 } ], "status" : "1" }

$unwind阶段:

  • 该阶段按 items 数组字段分解文档,items为每个数组元素输出一个文档。例如:
sit_rs1:PRIMARY> db.orders.aggregate( [
...    { $match: { ord_date: { $gte: new Date("2023-03-01") } } },
...    { $unwind: "$items" }
... ] )
{ "_id" : 2, "cust_id" : "A", "ord_date" : ISODate("2023-06-08T00:00:00Z"), "price" : 60, "items" : { "sku" : "apple", "qty" : 8, "price" : 2.5 }, "status" : "1" }
{ "_id" : 2, "cust_id" : "A", "ord_date" : ISODate("2023-06-08T00:00:00Z"), "price" : 60, "items" : { "sku" : "banana", "qty" : 5, "price" : 10 }, "status" : "1" }
{ "_id" : 3, "cust_id" : "B", "ord_date" : ISODate("2023-06-08T00:00:00Z"), "price" : 55, "items" : { "sku" : "apple", "qty" : 10, "price" : 2.5 }, "status" : "1" }
{ "_id" : 3, "cust_id" : "B", "ord_date" : ISODate("2023-06-08T00:00:00Z"), "price" : 55, "items" : { "sku" : "pears", "qty" : 10, "price" : 2.5 }, "status" : "1" }
{ "_id" : 7, "cust_id" : "C", "ord_date" : ISODate("2023-06-20T00:00:00Z"), "price" : 21, "items" : { "sku" : "apple", "qty" : 10, "price" : 2.5 }, "status" : "1" }
{ "_id" : 9, "cust_id" : "D", "ord_date" : ISODate("2023-06-20T00:00:00Z"), "price" : 51, "items" : { "sku" : "carrots", "qty" : 5, "price" : 1 }, "status" : "1" }
{ "_id" : 9, "cust_id" : "D", "ord_date" : ISODate("2023-06-20T00:00:00Z"), "price" : 51, "items" : { "sku" : "apples", "qty" : 10, "price" : 2.5 }, "status" : "1" }
{ "_id" : 9, "cust_id" : "D", "ord_date" : ISODate("2023-06-20T00:00:00Z"), "price" : 51, "items" : { "sku" : "apple", "qty" : 10, "price" : 2.5 }, "status" : "1" }
{ "_id" : 1, "cust_id" : "A", "ord_date" : ISODate("2023-06-01T00:00:00Z"), "price" : 15, "items" : { "sku" : "apple", "qty" : 5, "price" : 2.5 }, "status" : "1" }
{ "_id" : 1, "cust_id" : "A", "ord_date" : ISODate("2023-06-01T00:00:00Z"), "price" : 15, "items" : { "sku" : "apples", "qty" : 5, "price" : 2.5 }, "status" : "1" }
{ "_id" : 4, "cust_id" : "B", "ord_date" : ISODate("2023-06-18T00:00:00Z"), "price" : 26, "items" : { "sku" : "apple", "qty" : 10, "price" : 2.5 }, "status" : "1" }
{ "_id" : 10, "cust_id" : "D", "ord_date" : ISODate("2023-06-23T00:00:00Z"), "price" : 23, "items" : { "sku" : "apple", "qty" : 10, "price" : 2.5 }, "status" : "1" }
{ "_id" : 6, "cust_id" : "C", "ord_date" : ISODate("2023-06-19T00:00:00Z"), "price" : 38, "items" : { "sku" : "carrots", "qty" : 10, "price" : 1 }, "status" : "1" }
{ "_id" : 6, "cust_id" : "C", "ord_date" : ISODate("2023-06-19T00:00:00Z"), "price" : 38, "items" : { "sku" : "apples", "qty" : 10, "price" : 2.5 }, "status" : "1" }
{ "_id" : 5, "cust_id" : "B", "ord_date" : ISODate("2023-06-19T00:00:00Z"), "price" : 40, "items" : { "sku" : "banana", "qty" : 5, "price" : 10 }, "status" : "1" }
{ "_id" : 8, "cust_id" : "D", "ord_date" : ISODate("2023-06-20T00:00:00Z"), "price" : 76, "items" : { "sku" : "banana", "qty" : 5, "price" : 10 }, "status" : "1" }
{ "_id" : 8, "cust_id" : "D", "ord_date" : ISODate("2023-06-20T00:00:00Z"), "price" : 76, "items" : { "sku" : "apples", "qty" : 10, "price" : 2.5 }, "status" : "1" }

$group阶段

  • 该阶段按 items.sku 进行分组,计算每个 sku 的总数量。
  • order _ids 数组包括不相同的 items.sku 元素。
  • $addToSet : 返回所有唯一值的数组,这些值来自每个文档(使用相同字段group by 的一组文档中)。输出数组中元素的顺序未指定。
sit_rs1:PRIMARY> db.orders.aggregate( [
...    { $match: { ord_date: { $gte: new Date("2023-03-01") } } },
...    { $unwind: "$items" },
...    { $group: { _id: "$items.sku", qty: { $sum: "$items.qty" }, orders_ids: { $addToSet: "$_id" } }  }
... ] )
{ "_id" : "carrots", "qty" : 15, "orders_ids" : [ 6, 9 ] }
{ "_id" : "apples", "qty" : 35, "orders_ids" : [ 1, 6, 9, 8 ] }
{ "_id" : "banana", "qty" : 15, "orders_ids" : [ 8, 5, 2 ] }
{ "_id" : "apple", "qty" : 63, "orders_ids" : [ 10, 1, 7, 4, 9, 2, 3 ] }
{ "_id" : "pears", "qty" : 10, "orders_ids" : [ 3 ] }

$project阶段

  • 该阶段重塑输出文档以镜像映射缩减的输出,使其具有两个字段_id和 value。
  • 运算符 $divide 计算 订单平均数量。 即将一个数字除以另一个数字并返回结果。将参数传递给在一个数组中。
  • 使用 $size 来确定数组orders_ids的大小。
sit_rs1:PRIMARY> db.orders.aggregate( [
...    { $match: { ord_date: { $gte: new Date("2023-03-01") } } },
...    { $unwind: "$items" },
...    { $group: { _id: "$items.sku", qty: { $sum: "$items.qty" }, orders_ids: { $addToSet: "$_id" } }  },
...    { $project: { value: { count: { $size: "$orders_ids" }, qty: "$qty", avg: { $divide: [ "$qty", { $size: "$orders_ids" } ] } } } }
... ] )
{ "_id" : "apples", "value" : { "count" : 4, "qty" : 35, "avg" : 8.75 } }
{ "_id" : "carrots", "value" : { "count" : 2, "qty" : 15, "avg" : 7.5 } }
{ "_id" : "pears", "value" : { "count" : 1, "qty" : 10, "avg" : 10 } }
{ "_id" : "banana", "value" : { "count" : 3, "qty" : 15, "avg" : 5 } }
{ "_id" : "apple", "value" : { "count" : 7, "qty" : 63, "avg" : 9 } }

$merge阶段
最后,$merge将输出写入集合 agg_sku 。如果现有文档_id与新结果具有相同的键,则该操作将覆盖现有文档。如果不存在具有相同键的现有文档,则该操作将插入该文档。

sit_rs1:PRIMARY> db.orders.aggregate( [
...    { $match: { ord_date: { $gte: new Date("2023-03-01") } } },
...    { $unwind: "$items" },
...    { $group: { _id: "$items.sku", qty: { $sum: "$items.qty" }, orders_ids: { $addToSet: "$_id" } }  },
...    { $project: { value: { count: { $size: "$orders_ids" }, qty: "$qty", avg: { $divide: [ "$qty", { $size: "$orders_ids" } ] } } } },
...    { $merge: { into: "agg_sku", on: "_id", whenMatched: "replace",  whenNotMatched: "insert" } }
... ] )# 该操作返回以下文档:
sit_rs1:PRIMARY> db.agg_sku.find().sort( { _id: 1 } )
{ "_id" : "apple", "value" : { "count" : 7, "qty" : 63, "avg" : 9 } }
{ "_id" : "apples", "value" : { "count" : 4, "qty" : 35, "avg" : 8.75 } }
{ "_id" : "banana", "value" : { "count" : 3, "qty" : 15, "avg" : 5 } }
{ "_id" : "carrots", "value" : { "count" : 2, "qty" : 15, "avg" : 7.5 } }
{ "_id" : "pears", "value" : { "count" : 1, "qty" : 10, "avg" : 10 } }

聚合管道的限制

聚合管道对值类型和结果大小有一些限制:

  • 该aggregate命令可以返回游标或将结果存储在集合中。结果集中的每个文档均受 16 MB BSON 文档大小限制。如果任何单个文档超过BSON 文档大小限制,聚合就会产生错误。该限制仅适用于返回的文件。在管道处理过程中,文档可能会超过此大小。该 db.collection.aggregate()方法默认返回一个游标。

  • 每个单独的管道阶段的 RAM 限制为 100 MB。默认情况下,如果某个阶段超过此限制,MongoDB 会生成错误。$search
    聚合阶段不限于 100 MB RAM,因为它在单独的进程中运行

  • 如果管道阶段之一的结果$sort超出限制,请考虑添加 $limit stage 。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/10111.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C# 数据结构】Heap 堆

【C# 数据结构】Heap 堆 先看看C#中有那些常用的结构堆的介绍完全二叉树最大堆 Heap对类进行排序实现 IComparable<T> 接口 对CompareTo的一点解释 参考资料 先看看C#中有那些常用的结构 作为 数据结构系类文章 的开篇文章&#xff0c;我们先了解一下C# 有哪些常用的数据…

系统架构设计师 10:软件架构的演化和维护

一、软件架构演化 如果软件架构的定义是 SA{components, connectors, constraints}&#xff0c;也就是说&#xff0c;软件架构包括组件、连接件和约束三大要素&#xff0c;这类软件架构演化主要关注的就是组件、连接件和约束的添加、修改与删除等。 二、面向对象软件架构演化…

[oeasy]python0075_删除变量_del_delete_variable

删除变量 回忆上次内容 上次我们研究了字节序 字节序有两种 符号英文名称中文名称<little-endian小字节序>big-endian大字节序 字节序 用来 明确 整型数字存储的 顺序 如果 读写数字出了错 可以 考虑一下 是否 字节序出了问题 变量现在可以 声明初始化存储了 但是 …

thinkphp5拦截验证token

写一个BaseController 类 基本思路&#xff1a; 1、继承一个公共基类&#xff0c;将验证相关代码放在基类 2、根据 孩子类下的notNeedToken 来决定是否进行验证 3、验证失败后&#xff0c;直接响应回来 这里需要封装一个主要代码&#xff1a; protected function response($da…

Spring Boot中整合MyBatis(基于xml方式基于注解实现方式)

一、前提准备 在Spring Boot中整合MyBatis时&#xff0c;你需要导入JDBC&#xff08;不需要手动添加&#xff09;和Druid的相关依赖。 JDBC依赖&#xff1a;在Spring Boot中整合MyBatis时&#xff0c;并不需要显式地添加JDBC的包依赖。这是因为&#xff0c;当你添加mybatis-sp…

i.MX6ULL(二十) linux platform 设备驱动

Linux 系统要考虑到驱动的可重用性&#xff0c;因 此提出了驱动的分离与分层这样的软件思路&#xff0c;在这个思路下诞生了我们将来最常打交道的 platform 设备驱动&#xff0c;也叫做平台设备驱动。 1 Linux 驱动的分离与分层 1.1 驱动的分隔与分离 对于 Linux 这样一…

kubesphere安装中间件

kubesphere安装mysql 创建configMap [client] default-character-setutf8mb4[mysql] default-character-setutf8mb4[mysqld] init_connectSET collation_connection utf8mb4_unicode_ci init_connectSET NAMES utf8mb4 character-set-serverutf8mb4 collation-serverutf8mb4_…

macOS Monterey 12.6.8 (21G725) Boot ISO 原版可引导镜像

macOS Monterey 12.6.8 (21G725) Boot ISO 原版可引导镜像 本站下载的 macOS 软件包&#xff0c;既可以拖拽到 Applications&#xff08;应用程序&#xff09;下直接安装&#xff0c;也可以制作启动 U 盘安装&#xff0c;或者在虚拟机中启动安装。另外也支持在 Windows 和 Lin…

C# 翻转二叉树

226 翻转二叉树 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 1&#xff1a; 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1] 示例 2&#xff1a; 输入&#xff1a;root [2,1,3] 输出&#xff1a;…

问题解决Can‘t update table ‘category‘ in store

问题描述: 使用spring boot的时,候访问更新数据库内容接口报错: Error updating database. Cause: java.sql.SQLException: Cant update table category in stored function/trigger because it is already used by statement which invoked this stored function/trigger. 问题…

水文章——推荐一个视频播放器和一个图片查看器

视频播放器——PotPlayer http://www.potplayercn.com/ 图片查看器——JPEGVIEW https://www.bilibili.com/video/BV1ZY411P7fX/?spm_id_from333.337.search-card.all.click&vd_sourceab35b4ab4f3968642ce6c3f773f85138

QEMU源码全解析15 —— QOM介绍(4)

接前一篇文章&#xff1a;QEMU源码全解析14 —— QOM介绍&#xff08;3&#xff09; 本文内容参考&#xff1a; 《趣谈Linux操作系统》 —— 刘超&#xff0c;极客时间 《QEMU/KVM》源码解析与应用 —— 李强&#xff0c;机械工业出版社 特此致谢&#xff01; 上一回讲到pci…

wireshark导出H264裸流

导出H264裸流 安装wireshark下载rtp_h264_extractor.lua脚本配置lua脚本重启wireshark筛选 安装wireshark 下载抓包工具&#xff1a;首先&#xff0c;您需要下载并安装一个网络抓包工具&#xff0c;例如Wireshark&#xff08;https://www.wireshark.org&#xff09;或tcpdump&…

FTP服务器的搭建和配置上传脚本

文章目录 前言一、配置本地用户可上传权限ftp服务器1、用户登录ftp 二、配置FTP上传脚本文件1.脚本代码如下 补充知识 前言 vsftpd&#xff08;Very Secure FTP Daemon&#xff09;是一个在 Linux/Unix 系统上运行的一款开源免费的 FTP 服务器软件。vsftpd 支持支持 匿名用户、…

html2Canvas+jsPDF 下载PDF 遇到跨域的对象存储的图片无法显示

一、问题原因 对象存储的域名和你网址的域名不一样&#xff0c;此时用Canvas相关插件 将DOM元素转化为PDF&#xff0c;就会出现跨域错误。 二、解决办法 两步 1. 图片元素上设置属性 crossorigin"anonymous" 支持原生img和eleme组件 2. 存储桶设置资源跨域访问…

Python - Opencv + pyzbar实时摄像头识别二维码

直接上代码&#xff1a; import cv2 from pyzbar.pyzbar import decodecap cv2.VideoCapture(0) # 打开摄像头while True: # 循环读取摄像头帧ret, frame cap.read()# 在循环中&#xff0c;将每一帧作为图像输入&#xff0c;使用pyzbar的decode()函数识别二维码barcodes …

MFC表格控件CListCtrl的改造及用法

1、目的 简单描述MFC的表格控件使用方法。Qt适用习惯了以后MFC用的比较别扭&#xff0c;因此记录一下以备后续复制代码使用。由于MFC原生的CListCtrl比较局限&#xff0c;比如无法改变表格的背景色、文字颜色等设定&#xff0c;因此先对CListCtrl类进行重写&#xff0c;以便满足…

Carla教程一:动力学模型到LQR

Carla教程一、动力学模型到LQR 从运动学模型和动力学模型到LQR 模型就是可以描述车辆运动规律的模型。车辆建模都是基于自行车模型的设定,也就是将四个轮子抽象为自行车一样的两个轮子来建模。 1、运动学模型 运动学模型是基于几何关系分析出来的,一般适用于低俗情况下,…

EasyExcel数据导出功能封装

起因: 最近需要用到excel导出功能,使用EasyExcel可以快速实现导出,又需要优雅的对EasyExcel进行封装,在实现自己的导出功能时又可以制定一定的规则,让其他同事方便使用,最近研究了下网上的常规写法,站在巨人的肩上重新添加了自己的思路,供大家参考,有任何问题请多指教…

【监控系统】可视化工具Grafana简介及容器化部署实战

1.什么是Grafana 官网地址&#xff1a;https://grafana.com/ Grafana用Go语言开发的开源数据可视化工具&#xff0c;可以做数据监控和数据统计&#xff0c;带有告警功能。支持快速灵活的客户端图表&#xff0c;面板插件有许多不同方式的可视化指标和日志&#xff0c;官方库中…