ElasticSearch(九)— 聚集查询2

news2024/11/24 16:03:44

一、 范围分桶聚集

如果使用 SQL 语言类比,桶型聚集与 SQL 语句中的 group by 子句极为相似。桶型聚集(Bucket Aggregation)是 Elasticsearch 官方对这种聚集的叫法,它起的作用是根据条件对文档进行分组。

可以将这里的桶理解为分组的容器,每个桶都与一个分组标准相关联,满足
这个分组标准的文档会落桶中。所以在默认情况下,桶型聚集会根据分组标准返回所有分组,同时还会通过 doc_count 字段返回每一桶中的文档数量。

由于单纯使用桶型聚集只返回桶内文档数量,意义并不大,所以多数情况下
都是将桶型聚集与指标聚集以父子关系的形式组合在起使用。桶型聚集作为父聚集起到分组的作用。而指标聚集则以子聚集的形式出现在桶型聚集中, 起到分组统计的作用。比如将用户按性别分组,然后统计他们的平均年龄。

按返回桶的数量来看,桶型聚集可以分为单桶聚集和多桶聚集。在多桶聚集
中,有些桶的数量的固定的。而有些桶的数量则是在运算时动态决定。由于桶聚集基本都是将所有桶一次返回,返回了过多的通会影响性能,所以单个请求允许返间的最大桶数受 search.max_bucket 参数限制。

这个参数在 7.0 之前的版本中默认值为-1,代表无上限。但在Elasticsearch版本 7 中,这个参数的默认值已经更改为 10000 所以在做桶型聚集时要先做好数据验证,防止桶数量过多影响性能。

1.1 数值范围

range、date_range 与 ip_range 这三种类型的聚集都用于根据字段的值范围内对文档分桶,字段值在同一范围内的文档归入同一桶中。每个值范围都可通过from 和 to 参数指定,范围包含 from 值但不包含 to 值,用数学方法表示就是[from, to)。 在设置范围时,可以设置一个也可以设置多个,范围之间并非一定要连续,可以有间隔也可以有重叠。

range 聚集

range 聚集使用 ranges 参数设置多个数值范围,使用 field 参数指定 1 个数值类型的字段。range 聚集在执行时会将该字段在不同范围内的文档数量统计出来,并在返回结果的 doc_count 字段中展示出来。例如统计航班不同范围内的票价数量,可以按示例的方式发送请求:

POST indexname/_search?filter_path=aggregations{
	"aggs": {
		"price_ranges": {
			"range": {
				"field": "AvgTicketPrice",
				"ranges": [{
					"to": 300
				},
				{
					"from": 300,
					"to": 600
				},
				{
					"from": 600,
					"to": 900
				},
				{
					"to": 900
				}]
			}
		}
	}
}

在返回结果中,每个范围都会包含一个 key 字段,代表了这个范围的标识,它的基本格式是“- "。如果觉得返回的这种 key 格式不容易理解,可以通过在 range 聚集的请求中添加 keyed 和 key 参数定制返回结果的 key 字段值。其中 keyed 是 range 的参数,用于标识是否使用 key 标识范围,所以为布尔类型,key 参数则是与 from、to 参数同级的参数,用于定义返回结果中的 key 字段值。

date_range 聚集

date_range 聚集与 range 聚集类似,只见范围和字段的类型为日期而非数值。
date_range 聚集的范围指定也是通过 ranges 参数设置,具体的范围也是使
用- 两个参数,并且可以使用 keyed 和 key 定义返回结果的标识。
date_range 聚集多了个指定日期格式的参数 format, 可以用于指定 from 和 to 的目期格式。例如,

POST indexname/_search?filter_path=aggregations{
	"aggs": {
		"mar_flights": {
			"date_range": {
				"field": "timestamp",
				"ranges": [{
					"from": "2019-03-01",
					"to": "2019-03-30"
				}],
				"format": "yyyy-MM-dd"
			}
		}
	}
}

ip_range 聚集

ip_ range 聚集根据 ip 类型的字段统计落在指定 IP 范围的文档数量,使用的聚集类型名称为 ip_ range。例如,统计了两个 IP 地址范围的文档数量:

POST indexname/_search?filter_path=aggregations{
	"aggs": {
		"local": {
			"ip_range": {
				"field": "clientip",
				"ranges": [{
					"from": "157.4.77.0",
					"to": "157.4.77.255"
				},
				{
					"from": "105.32.127.0",
					"to": "105.32.127.255"
				}]
			}
		}
	}
}

1.2 间隔范围

histogram、date _ histogram 与 auto_date_histogram 这三种聚集与上一节中使用数值定义范围的聚集很像,也是统计落在某一范围内的文档数量。 但与数值范围聚集不同的是,这三类座集统计范围由固定的间隔定义,也就是范围的结束值和起始值的差值是固定的。

histogram 聚集

histogram 聚集以数值为间隔定义数值范围,字段值具有相同范围的文档将
落入同桶中。例如示例以 100 为间隔做分桶,可以通过返回结果的 doc_count 字段获取票价在每个区间的文档数量:

POST indexname/_search?filter_path=aggregations{
	"aggs": {
		"price_histo": {
			"histogram": {
				"field": "AvgTicketPrice",
				"interval": 100,
				"offset": 50,
				"keyed": false,
				"order": {
					"_count": "asc"
				}
			}
		}
	}
}

其中,interval 参数用于指定数值问隔必须为正值,而 offset 参数则代表起
始数值的偏移量,必须位于[0, interval) 范围内。order 参数用于指定排序字段和顺序,可选字段为_key 和_count。当 keyed 参数设置为 true 时,返回结果中每个桶会有一个标识,标识的计算公式为:

bucket_key = Math. floor( ( value- offset)/interval) * interval +offset

date_histogram 聚集

date_histogra 聚集以时间为间隔定义日期范围,字段值具有相同日期范围的文档将落入同一桶中。同样,返回结果中也会包含每个间隔范围内的文档数量doc_count。 例如统计每月航班数量:

POST indexname/_search?filter_path=aggregations{
	"aggs": {
		"month flights": {
			"date_histogram": {
				"field": "timestamp",
				"interval": "month"
			}
		}
	}
}

在示例使用参数 interval 指定时间间隔为 month,即按月划分范围。时间可以是还有:

毫秒:1ms 10ms
秒:second/1s 10s
分钟:minute/1m 10m
小时:hout/1h 2h
天:day 2d 不支持
星期:week/1w 不支持
月:month/1M 不支持
季度:quarter/1q 不支持
年:year/1y 不支持

auto_date_histogram 聚集

前述两种聚集都是指定间隔的具体值是多少,然后再根据间隔值返回每一
桶中满足条件的文档数。最终会有多少桶取决于两个条件,即间隔值和字段值在所有文档中的实际跨度。反过来,如果预先指定需要返回多少个桶,那么间隔值也可以通过桶的数量以及字段值跨度共同确定。auto_date_histogram 聚集就是这样一种聚集,它不是指定时间间隔值,而是指定需要返回桶的数量。例如在示例中定义需要返回 10 个时间段的桶:

POST indexname/_search?size=0{
	"aggs": {
		"age_group": {
			"auto_date_histogram": {
				"field": "timestamp",
				"buckets": 10
			}
		}
	}
}

参数 field 设置通过哪一个字段做时间分隔,而参数 buckets 则指明了需要返回多少个桶。 默认情况下, buckets 的数量为 10。需要注意的是,buckets 只是设置了期望返回桶的数量,但实际返回桶的数量可能等于也可能小于 buckets设置的值。例如示例的请求中期望 10 个桶,但实际可能只返回 6 个桶。
auto_date_histogram 聚集在返回结果中还提供了一个 interval 字段,用于说明实际采用的间隔时间。从实现的角度来说,不精确匹配 buckets 数量也有利于提升检索的性能。

1.3 子聚集 (聚集嵌套)

前面介绍的桶型聚集,大部分都只是返回满足聚集条件的文档数量。在实际
应用中,如果需要桶型聚集与 SQL 中的 group by 具有相同的意义,用于将文档分桶后计算各桶特定指标值,比如根据用户性别分组,然后分别求他们的平均年龄。Elasticsearch 这样的功能通过子聚集 (聚集嵌套)来实现。例如,示例中的请求就是先按月对从中国起飞的航班做了分桶,然后又通过聚集嵌套计算每月平均延误时间:

POST indexname/_search?filter_path=aggregations{
	"query": {
		"term": {
			"OriginCountry": "CN"
		}
	},
	"aggs": {
		"date_price_histogram": {
			"date_histogram": {
				"field": "timestamp",
				"interval": "month"
			},
			"aggs": {
				"avg_price": {
					"avg": {
						"field": "FlightDelayMin"
					}
				}
			}
		}
	}
}

在示例中,search 接口共使用了两个参数,query 参数以 term 查询条件将所有 OriginCountry 字段是 CN 的文档筛选出来参与聚集运算。
aggs 参数则定义了一个名称为 data_price_histogram 的桶型聚集,这个聚集内部又嵌套了个名称为 avg
price 的聚集。由于 price 这个聚集位于 data_price histogram 中,所以它会使用这个聚集的分桶结果做运算而不会针对所有文档。所以,最终的效果就是将按月计算从中国出发航班的平均延误时间。
使用嵌套聚集时要注意,嵌套聚集应该位于父聚集名称下而与聚集类型同级,并且需要通过参数再次声明。如果与父聚集一样位于 aggs 参数下,那么这两个聚集就是平级而非嵌套聚集。

二、词项分桶聚集

使用字段值范围分桶主要针对结构化数据,比如年龄、IP 地址等等。但对于字符串类型的字段来说,使用值范围来分桶显然是不合适的。由于字符串类型字段在编入索引时会通过分析器生成词项,所以字符申类型字段的分桶一般通过词项实现。使用词项实现分桶的聚集,包括 terms、significant_terms 和significant_text 聚集。由于使用词项分桶需要加载所有词项数据,所以它们在执行速度上都会比较慢。为了提升性能,Elsticesearch 提供了 sampler 和diversifed_sampler 聚集,可通过缩小样本数量减少运算量。

2.1 terms 聚集

terms 聚集根据文档字段中的词项做分桶,所有包含同一词项的文档将被归人同一桶中,聚集结果中包含字段中的词项及其词频,在默认情况下还会根据词频排序,所以 terms 聚集也可用于热词展示,由于 terms 聚集在统计词项的词频数据时需要打开它的 fielddata 机制。fielddata 机制对内存消耗较大且有导致内存溢出的可能, 所以 terms 聚集一般针对 keyword 非 text 类型。

Fielddata:其实根据倒排索引反向出来的一个正排索引,即 document 到 term的映射。

只要我们针对需要分词的字段设置了 fielddata,就可以使用该字段进行聚合,排序等。我们设置为 true 之后,在索引期间,就会以列式存储在内存中。为什么存在于内存呢,因为按照 term 聚合,需要执行更加复杂的算法和操作,如果基于磁盘或者 OS 缓存,性能会比较差。

fielddata 堆内存要求很高,如果数据量太大,对于 JVM 来及回收来说存在一定的挑战,也就是对 ES 带来巨大的压力。所以 doc_value 的出现我们可以使用磁盘存储,他同样是和 fielddata 一样的数据结构,在倒排索引基础上反向出来的正排索引,并且是预先构建,即在建倒排索引的时候,就会创建 doc values。, 这会消耗额外的存储空间,但是对于 JVM 的内存需求就会减少。总体来看,DocValues 只是比 fielddata 慢一点,大概 10-25%,则带来了更多的稳定性。

cardlinality 聚集可以统计字段中不重复词项的数量,而 terms 聚集则可以将这些词项全部展示出来。与 cardlinality 聚集一样, terms 聚集统计出来的词频也不能保证完全精确。例如:

POST indexname/_search?filter_path=aggregations{
	"aggs": {
		"country_terms": {
			"terms": {
				"field": "DestCountry",
				"size": 10
			}
		},
		"country_terms_count": {
			"cardinality": {
				"field": "DestCountry"
			}
		}
	}
}

在示例中定义了两个聚集,由于它们都是定义在 aggs 下,所以不是嵌套聚集。terms 聚集的 field 参数定义了提取词项的字段为 DestCountry, 它的词项在返回结果中会按词频由高到低依次展示,词频会在返回结果的 doc_count 字段中展示。另一个参数 size 则指定了只返回 10 个词项,这相当把 DestCountry 字段中词频前 10 名检索出来。

2.2 significant_terms 聚集

terms 聚集统计在字段中的词项及其词频,聚集结果会按各词项总的词频排序,并讲现次数最多的词项排在最前面,这非常适合做推荐及热词类的应用。但按词频总数不一定可能是总是正确的选择,在一些检索条件已知的情况下,一些词频总数比较低的词项反而是更合适的推荐热词。

举例来说,假设在 10000 篇技术类文章的内容中提到 Elasticsearch 有 200 篇,占比为 2%;但在文章标题含有 NoSQL 的 1000 篇文章中,文章内容提到Elasticsearch 的为 180 篇,占比为 18%。 这种占比显著的提升,说明在文章标题含有 NoSQL 的条件下,Elasticsearch 变得更为重要。换句话说,如果一个词项在某个文档子集中与在文档全集中相比发生了非常显著的变化,就说明这个词项在这个文档子集中是更为重要的词项。

significant_terms 聚集就是针对上述情况的一种聚集查询,它将文档和词项分为前景集 Foreground Set 和背景集(Background Set)。前景集对应一个文档子集,面背景集则对应文档全集。significant_terms 聚集根据 query 指定前景集,运算field 参数指定字段中的词项在前景集和背景集中的词频总数,并在结果的doc_coumt 和 bg_coumt 中保存它们。例如:

POST indexname/_search?filter_path=aggregations{
	"query": {
		"term": {
			"OriginCountry": {
				"value": "IE"
			}
		}
	},
	"aggs": {
		"dest": {
			"significant_terms": {
				"field": "DestCountry"
			}
		}
	}
}

在示例中,query 参数使用 DSL 指定了前景集为出发国家为 IE (即爱尔兰)的航班,而聚集查询中则使用 significant_ terms 统计到达国家的前景集词频和背景集词频。来看下返回结果:
在这里插入图片描述
在返回结果中,前景集文档数量为 119,背景集文档数量为 13059。
在 buckets 返回的所有词项中,国家编码为 GB 的航班排在第一位。它在前景集中的词频为 12,占比约为 10% (12/119); 而在背景集中的词频为 449,占比约为 3. 4% (445/13059)。
词项 GB 在前景集中的占比是背景集中的 3 倍左右,发生了显著变化,所以在这个前景集中 GB 可以被视为热词而排在第一位。GB 代表的国家是英国,从爱尔兰出发去英国的航班比较多想来也是合情合理的。
除了按示例方式使用 quey 参数指定前景集以外,还可以将 terms 聚集与significant_terms 聚集结合起来使用,这样可以一次性列出一个字段的所有前景集的热词。例如:

POST indexname/_search?filter_path=aggregations{
	"aggs": {
		"orgin_dest": {
			"terms": {
				"field": "OriginCountry"
			},
			"aggs": {
				"dest": {
					"significant_terms": {
						"field": "DestCountry"
					}
				}
			}
		}
	}
}

在示例中,使用 terms 聚集将 OriginCountry 字段的词项全部查询出来做前景集,然后再与 significant_terms 聚集起查询它们的热词。

2.3 significant_text 聚集

如果参与 significant_terms 聚集的字段为 text 类型,那么需要将字段的fielddata 机制开启,否则在执行时会返回异常信息。significant_text 聚集与significant_terms 聚集的作用类型,但不需要开启字段的 fielddata 机制,所以可以把它当成是种专门为 text 类型字段设计的 significant_terms 聚集。例如在kibana_sample_data_logs 中,message 字段即为 text 类型,如果想在这个字段上做词项分析就需要使用 significant_terms 聚集:

POST indexname/_search?filter_path=aggregations{
	"query": {
		"term": {
			"response": {
				"value": "200"
			}
		}
	},
	"aggs": {
		"agent_term": {
			"significant_text": {
				"field": "message"
			}
		}
	}
}

在示例中,前景集为响应状态码 response 为 200 的日志,significant_text 聚集则查看在这个前景集下 message 字段中出现异常热度的词项。返回结果片段:
在这里插入图片描述
通过展示的返回结果可以看出,排在第一位的词项 200 在前景集和背景集中的数量是一样的, 这说明 message 中完整地记录了 200 状态码;而排在第二位的词项 beats 前景集和背景集分别为 3462 和 3732。这说明请求“/beats" 地址的成功率要远高于其他地址。

significant_text 聚集之所以不需要开启fielddata机制是因为它会在检索时对text 字段重新做分析,所以 significant_text 聚集在执行时速度比其他聚集要慢很多。如果希望提升执行效率,则可以使用 sampler 聚集通过减少前景集的样本数量降低运算量。

2.4 样本聚集

sampler 聚集的作用是限定其内部嵌套聚集在运算时采用的样本数量。sampler 提取样本时会按文档检索的相似度排序,按相似度分值由高到低的顺序提取。例如:

POST indexname/_search?filter_path=aggregations{
	"query": {
		"term": {
			"OriginCountry": {
				"value": "IE"
			}
		}
	},
	"aggs": {
		"sample_data": {
			"sampler": {
				"shard_size": 100
			},
			"aggs": {
				"dest_country": {
					"significant_terms": {
						"field": "DestCountry"
					}
				}
			}
		}
	}
}

在示例中共定义了 sample_ data 和 dest_country 两个聚集,其中dest_country 是 sample_data 聚集的子聚集或嵌套聚集,因此 dest_country 在运算时就只从分片上取一部分样本做运算。sampler 聚集的 shard_size 就是定义了每个分片上提取样本的数量,这些样本会根据 DSL 查询结果的相似度得分由高到低的顺序提取。

执行后会发现,这次目的地最热的目的地国家由 GB 变成了 KR,这就是样本范围缩小导致的数据失真。为了降低样本减少对结果准确性的影响,需要将些重复的数据从样本中剔除。换句话说就是样本更加分散,加大样本数据的多样性。Elasticsearch 提供的 diversified_sampler 聚集提供了样本多样性的能力,它提供了field 或 script 两个参数用于去除样本中可能重复的数据。由于相同航班的票价可能是相同的,所以可以将票价相同的航班从样本中剔除以加大样本的多样性,例如:

POST indexname/_search?filter_path=aggregations{
	"query": {
		"term": {
			"OriginCountry": {
				"value": "IE"
			}
		}
	},
	"aggs": {
		"sample_data": {
			"diversified_sampler": {
				"shard_size": 100,
				"field": "AvgTicketPrice"
			},
			"aggs": {
				"dest_country": {
					"significant_terms": {
						"field": "DestCountry"
					}
				}
			}
		}
	}
}

diversified_sampler 通过 field 参数设置了 AvgTicketPrice 字段,这样在返回结果中 GB 就又重新回到了第一位。

三、 单桶聚集

前面介绍的桶型聚集都是多桶型聚集,本章主要介绍单桶聚集。
单桶聚集在返回结果中只会形成一个桶,它们都有比较特定的应用场最。在Elasticsearch 中,单桶聚集主要包括 filter,global, missing 等几种类型。另外还有一种 filters 聚集,它虽然属于多桶聚集, 但与 filter 聚集很接近,所以放到一起说明。

3.1 过滤器聚集

过滤器聚集通过定义一个或多个过滤器来区分桶,满足过速器条件的文档将落入这个过滤器形成的桶中。过滤器聚集分为单桶和多桶两种,对应的聚集类型自然就是 filter 和 filters。
filter 桶型聚集属于单桶型聚集,一般会同时嵌套一个指标聚集,用于在过滤后的文档范围内计算指标,例如:

POST indexname/_search?size=0&filter_path=aggregations
{
	"aggs": {
		"origin_cn": {
			"filter": {
				"term": {
					"OriginCountry": "CN"
				}
			},
			"aggs": {
				"cn_ticket_price": {
					"avg": {
						"field": "AvgTicketPrice"
					}
				}
			}
		},
		"avg_price": {
			"avg": {
				"field": "AvgTicketPrice"
			}
		}
	}
}

在示例中一共定义了 3 个聚集,最外层是两个聚集,最后聚集为嵌套聚集,origin_cn 聚集为单过滤器的桶型聚集,它将所有 OriginCountry 为 CN 的文档归入一桶。

origin_cn 桶型聚集嵌套了 cn_ticket_price 指标聚集, 它的作用是计算当前桶内文档 AvgTicketPrice 字段的平均值。另一个外层聚集 avg_price 虽然也是计算 AghckePie 字段的平均值,但它计算的是所有文档的平均值。实际上,使用 query与 agg 结合起来也能实现类似的功能,区别在于过滤器不会做相似度计算,所以效率更高一些也更灵活一些。

多过滤器与单过滤器的作用类似,只是包含有多个过滤器,所以会形成多个桶。多过滤博型聚集使用 filters 参数接收过滤条件的数组,一般也是与指标聚集一同使用。例:

POST indexname/_search?size=0&filter_path=aggregations
{
	"aggs": {
		"origin_cn_us": {
			"filters": {
				"filters": [{
					"term": {
						"OriginCountry": "CN"
					}
				},
				{
					"term": {
						"OriginCountry": "US "
					}
				}]
			},
			"aggs": {
				"avg_ price": {
					"avg": {
						"field": "AvgTicketPrice"
					}
				}
			}
		}
	}
}

以上示例是使用两个过滤器计算从中国、美国出发的航班平均机票价格。

3.2 global 聚集

global 桶型聚集也是一种单桶型聚集, 它的作用是把索引中所有文档归入一个桶中。这种桶型聚集看似没有什么价值,但当 global 桶型聚集与 query 结合起来使用时,它不会受 query 定义的查询条件影响,最终形成的桶中仍然包含所有文档。global 聚集在使用上非常简单,没有任何参数。

POST indexname/_search?size=0&filter_path=aggregations
{
	"query": {
		"term": {
			"Carrier": {
				"value": "Kibana Airlines"
			}
		}
	},
	"aggs": {
		"kibana_avg_delay": {
			"avg": {
				"field": "FlightDelayMin"
			}
		},
		"all flights": {
			"global": {
				
			},
			"aggs": {
				"all_avg_delay": {
					"avg": {
						"field": "FlightDelayMin"
					}
				}
			}
		}
	}
}

以上示例中 query 使用 term 查询将航空公司为“Kibana Airline"的文档都检索出来,而 kibana _avg delay 定义的平均值聚集会将它们延误时间的平均值计算出来。但另个 all_fights 聚集由于使用了 global 聚集所以在嵌套的 all_avg_delay 聚集中计算出来的是所有航班廷误时间的平均值。

3.3 missing 聚集

missing 聚集同样也是一种单桶型聚集,它的作用是将某一字段缺失的文档归入一桶。
missing 聚集使用 field 参数定义要检查缺失的字段名称,例如:

POST indexname/_search?filter_path=aggregations
{
	"aggs": {
		"no_price": {
			"missing": {
				"field": "AvgTicketPrice"
			}
		}
	}
}

示例将 kibana_sample_data_flights 中缺失 AvgTicketPrice 字段的文档归入一桶,通过返回结果的 doc_count 查询数量也可以与指标聚集做嵌套,计算这些文档的某一指标值。

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

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

相关文章

git commit 提交报错

当使用git cimmit -m "XXX" 将暂存区文件提交到仓库区时出现以下错误信息: 原因:开启了 eslint 校验 只要跳过 eslint 校验就可以了,即加 --no-verify 即可解决 git commit --no-verify -m "XXX"

太极图形学——弹性物体仿真 1

1.仿真基础,时间和空间的离散化 渲染对于物体的展现来说是一件很重要的事 但除了渲染之外,还需要物理来控制,形成动画 弹性物体的仿真实际上非常重要,特别是对于头发,衣物的仿真,虚拟手术中软组织的仿真 仿…

JupyterNotebook添加Anaconda中已有的虚拟环境

比如,在Acaconde中存在一个我已经配置好的虚拟环境pose,现在我想在Jupyter中使用它 那么可以使用ipython kernel install --user --name 你要添加的环境 添加到Jupyter中。 对于Jupyter中已有的代码,就可以在Kernel - chanage kernel中改变内核。

大模型+XDR!打开网络安全攻防演练新范式!

网络安全领域面临着日益复杂的挑战,外部攻击与内部安全威胁交织的双重压力。技术革新成为筑牢安全防线的关键,随着新一代技术的崛起,特别是大数据与人工智能的深度融合,引领着网络安全进入全新阶段。 通过构建网络安全大模型&…

批量重命名图片文件名,这几种方法告别手打!

在这个数字化时代,图片已成为我们日常生活和工作中不可或缺的一部分。无论是整理旅行照片、管理项目素材,还是编辑文章配图,图片的管理都显得尤为重要。然而,面对成百上千的图片文件,如果还在逐一手动修改文件名&#…

OpenSNN推文:研究发现,人工智能以牺牲集体多样性为代价提升个人创造力

 ChatGPT 等生成式 AI 工具的兴起引发了关于它们对创造力和新颖想法产生的影响的争论。 伦敦大学管理学院和埃克塞特大学研究人员开展的一项新研究探索了生成模型对创意写作的影响。该研究考察了获取大型语言模型 (LLM) 生成的故事创意如何影响人类创…

使用 Python 执行 JavaScript

案例引入 网站: https://spa7.scrape.center 这里是一个简单的 NBA 球星的网站, 用卡片形式展示了一些球星的基本信息。另外,每张卡片其实都有一个加密字符串,这个加密字符串其实和球星的信息是由关联的, 并且每个球星…

数据库范式及其示例,看完这一篇足够

1. 什么是数据库规范化? 1.1 规范化概念 规范化是一种数据库设计技术,可减少数据冗余并消除插入、更新和删除异常等不良特征。规范化规则将较大的表划分为较小的表并使用关系链接它们。SQL 中的规范化的目的是消除冗余(重复)数据…

Java面试题:Spring循环引用(循环依赖)

Spring中的循环引用 在创建A时需要B,创建B时需要A 三级缓存解决循环依赖问题 在Spring中定义了一个类 DefaultSingletonBeanRegistry 中定义了三个map singletonObjects 一级缓存 单例池,存放完整初始化的bean对象 earlySingletonObjects 二级缓存 缓存早期的bean对象…

【JavaEE初阶】CAS(比较和交换)

目录 🌲 什么是 CAS 🌳 CAS的应用 🚩 实现原子类 🚩 实现自旋锁 🎄 CAS 的 ABA 问题 🚩 什么是 ABA 问题 🚩 ABA 问题引来的 BUG 🚩 解决方案 🍀CAS相关面试题 …

自动化测试客户端程序 时,选择使用什么自动化测试工具?

自动化测试客户端程序时,可以选择多种自动化测试工具,这些工具根据测试的具体需求、目标平台以及开发语言等因素有所不同。以下是一些常用的自动化测试工具,它们分别适用于不同的测试场景: 1. Appium 简介:Appium是一…

你要动态建表,还要动态导入Excel?

背景 ⭐⭐⭐⭐⭐转载请注明出处:https://juejin.cn/post/7400945359192866828 前几天和公司的小伙伴聊天的时候,得知他们的项目里正要做一个功能。大概就是每家公司都会建一张表,这张表会有什么字段不确定,可能有的表10个字段,有的8个字段。然后会有导入的功能,就是给这张…

java实现解析pdf格式发票

为了减少用户工作量及误操作的可能性&#xff0c;需要实现用户上传PDF格式的发票&#xff0c;系统通过解析PDF文件获取发票内容&#xff0c;并直接将其写入表单。以下文章记录了功能实现的代码。 发票样式 发票内容解析 引用Maven 使用pdfbox <dependency><groupI…

API可观察性对于现代应用程序的最大好处

API可观察性是提升性能、加速问题诊断和增强安全的关键。它在理解和管理错综复杂的API交互方面发挥着至关重要的作用。利用API可观察性&#xff0c;您可以深入洞察API的工作状态&#xff0c;保障服务的可靠性&#xff0c;并优化用户体验。 在当今的数字环境中&#xff0c;API …

kubernetes集群部署sql server数据库服务

背景&#xff1a; 因业务上线需要&#xff0c;研发中心要求在kubernetes测试集群部署一个sql server 2017的数据库&#xff0c;用于业务功能调试。 一、实施部署sql server数据库&#xff1a; 1、拉取sql server 2017的镜像&#xff1a; [rootharbor-02 ~]# docker pull mcr…

POI导出复杂Excel表格

记录在遇到复杂统计报表业务时&#xff0c;无法使用Excel模板生成对应报表&#xff0c;则采用最原始poi方式进行创建生成 业务所需统计报表如下图 麻烦所在各类型订单下方餐别为动态数据&#xff0c;废话不多说直接上代码 new CellRangeAddress(起始行号, 终止行号, 起始列号,…

Android Studio 设置打开layout.xml文件的默认视图split

Android Studio 设置打开layout.xml文件的默认视图 Android Studio 设置打开layout.xml文件的默认视图 androd studio 在使用的时候打开我们自己的布局文件默认展示的视图为Design,我们想要编辑的时候还有手动切换成splite 视图或者Code视图&#xff0c;不上很方便&#xff0c…

CA证书和openssl介绍

文章目录 一、加密和算法常见的安全攻击加密算法和协议对称加密非对称加密算法 二、CA和证书中间人攻击CA和证书安全协议SSL/TLS协议介绍HTTPS 三、opensslopenssl介绍使用openssl实现对称加密使用openssl命令生成加密密码生成随机密码建立私有CA证书申请颁发建立私有CA实际例子…

Java-数据库基本概念

数据库DataBase 定义: 保存一组数据的仓库就是数据库 例 BirdBoot项目中&#xff0c;我们为了保存一组用户信息&#xff0c;创建了一个目录users。里面用若干个文件保存每一个用户信息 此时users目录就可以称为是一个数据库 只不过对于这些数据的维护操作&#xff0c;要么…

【最多可以参加的会议数目】python刷题记录

R4-贪心篇 结束时间升序排列优先队列 class Solution:def maxEvents(self, events: List[List[int]]) -> int:dictdefaultdict(list)for i,val in enumerate(events):dict[val[0]].append(val[1])#优先队列&#xff08;小根堆&#xff09;h[]ret0for i in range(1,100001)…