自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(313)
  • 资源 (1)
  • 收藏
  • 关注

原创 lucene 段 leaf” 就是 “segment(段)” 的别名。

因此,`LeafReaderContext` 中的 leaf 指的就是 “当前正在处理的这一个 segment”。`LeafReaderContext` 就是 “这个 segment 的上下文对象”。在 Lucene 里,“leaf” 就是 “segment(段)” 的别名。- 每个 segment 被封装为一个 LeafReader。- 一个完整的索引由 多个只读 segment 组成。> leaf = segment = 只读的最小索引单元。

2025-07-17 08:59:54 156

原创 Elasticsearch 线程池

**FIXED** | 固定大小线程池 | 线程数固定,队列大小也固定。| **SYSTEM_CRITICAL_READ / SYSTEM_CRITICAL_WRITE** | **FIXED** | 关键系统操作(如安全认证),独立固定线程保障 QoS。| **SCALING** | 弹性线程池 | 线程数按需创建,**空闲线程会被回收**。| **DIRECT** | 直接执行(无线程池) | 任务在当前线程中同步执行,**不切换线程**,**无队列**,**无并发限制**。

2025-07-12 20:10:28 503

原创 【Elasticsearch 】search_throttled

search_throttled` 是 Elasticsearch 中的一个 **专用线程池**,其作用是 **专门处理那些被“节流(throttled)”的索引上的搜索类请求**,例如 `count`、`search`、`suggest`、`get` 等操作。> `search_throttled` 是 Elasticsearch 为 **冻结或低优先级索引** 准备的“慢车道”线程池,**线程数只有 1,队列也很小**,目的是 **保护集群性能不被冷数据拖垮**。### ✅ 总结一句话。

2025-07-12 19:43:45 301

原创 【Elasticsearch】function_score与rescore

• 时机:各分片先用原始查询拿到 **window 内的 Top-K**(默认 10×page_size),然后只在 **这 K 个文档** 上重新算分;- 把 **phrase proximity**、**sloppy 查询** 放在 rescore 里,避免对全量文档计算。- 用 **昂贵脚本** 或 **复杂机器学习模型** 给 Top-K 做二次精排。> **function_score** 在 **第一次算分** 时就动手脚;• 性能:对 **全部命中文档** 都生效,数据量大时成本最高。

2025-07-12 18:55:19 462

原创 BKD 树(Block KD-Tree)Lucene

• 所有 `long`, `integer`, `double`, `date`, `ip`, `geo_point`, `geo_shape`, `dense_vector` 字段,**默认**就用 BKD 树存维度数据;),**不存文本倒排**。• 所有叶子块再建一个 **内存索引**(min-max 值 + 文件指针),查询时先扫内存索引→定位少量磁盘块→顺序读,几乎无随机 IO。• 每满 1024 个点就写成一个 **block**(顺序磁盘页),天然压缩 & 缓存友好。3. **支持的查询**

2025-07-12 18:42:40 374

原创 复杂查询(wildcard、range、geo、script)分别说一下它们是怎么重写的?

2. 用 **Automaton**(通配符自动机)在字典里 **顺序遍历** 所有以 `jav` 开头的真实词项,例如:`java`, `javascript`, `javaw`。2. 在 BKD 树中 **点范围查询**,一次性拿到所有落在 `[50, 100)` 的 **docId 位图**。核心思路都是“**先把索引里真正命中的底层 Term 或点集合找出来,再组合成可快速倒排扫描的原子查询**”。2. 重写阶段 **原样保留**(`ScriptQuery` 本身已是原子查询)。

2025-07-12 18:42:00 242

原创 【Lucene/Elasticsearch】**Query Rewrite** 机制

**把“高级”或“逻辑”查询(如 PrefixQuery、WildcardQuery、RangeQuery)在真正执行前,拆成最底层的、可直接倒排索引查的“原子查询”(TermQuery、PointRangeQuery 等)。- 重写由 `Query.rewrite(IndexReader)` 触发,发生在 **搜索执行早期**(QueryPhase 之前)。用户写的查询 → 重写后的查询。1. **高级查询本身无法直接走索引**2. **拆成原子查询后可走优化路径**

2025-07-12 18:41:21 429

原创 【Lucene/Elasticsearch】 数据类型(ES 字段类型) | 底层索引结构

`text`、`keyword`(字符串) | **倒排索引 + 正排 doc values** | 分词或不分词的倒排列表 || `completion`、`search_as_you_type` | **专用 FST** | 用于前缀/补全,不走倒排 || `object`、`nested`、`flattened` | **子字段递归索引** | 内部仍是倒排/BKD 组合 |• 先根据用户输入的前缀或模糊模式,在 **FST** 里快速定位到 **所有候选 term** 的起止位置。

2025-07-12 18:40:07 368

原创 【Elasticsearch】昂贵算法与廉价算法

,它们要么 **逐条做复杂计算**,要么 **随机磁盘读**,要么 **内存膨胀**;在 Elasticsearch 里,“昂贵”并不单指“CPU 时间”,而是综合了 **CPU、内存、磁盘 I/O、网络传输** 以及 **实现复杂度** 的代价。| **Term 级查询** | `term`, `terms`, `range`(数值/日期) | 直接查倒排列表,O(log N) 跳表 || **Filter 子句** | `bool.filter` | 只算位图交集,**不计分、可缓存** |

2025-07-12 18:33:26 359

原创 【Elasticsearch】post_filter

也就是说如果在聚合之前进行过滤,然后进行聚合,聚合的内容其实是针对于过滤后的文档进行的,比如如果聚合是求平均分,如果先过滤 那么聚合的时候 针对的就是过滤后的文档进行求平均,而是用post_filter 在聚合之后 针对返回的hits文档过滤 不影响聚合 聚合是针对全部的文档来求平均。post_filter是在进行聚合之后,再对最终返回的文档列表做额外过滤,不破坏那份聚合/统计的完整性”**。时,post_filter 才成为“不破坏聚合”的工具。里即可,post_filter 完全没必要。

2025-07-12 17:29:11 260

原创 `\\?\` 是 **Windows 特有的“长路径前缀”(long-path prefix)**,正式名称叫 **UNC 扩展路径(Extended-Length Path)**。

` 前缀**,确保在极深目录或超长路径下也能正常加载,避免 **“路径过长”** 导致的 `ERROR_PATH_NOT_FOUND` 或 `CreateProcess` 失败。\` 是 **Windows 特有的“长路径前缀”(long-path prefix)**,正式名称叫 **UNC 扩展路径(Extended-Length Path)**。必须以 **绝对路径** 形式出现,且 **不能包含 `.` 或 `..`**。Windows 默认路径限制为 **260 字符**(含结尾 `\0`)。

2025-07-12 13:38:06 234

原创 Elasticsearch 的 `modules` 目录

Elasticsearch 的 `modules` 目录是存放**核心功能模块**的目录,这些模块是 Elasticsearch 运行所必需的基础组件,**随官方发行版一起提供**,但设计上允许通过移除或替换模块来**定制化部署**(比如构建一个最小化的 Elasticsearch 实例)。| **示例** | `transport-netty4`、`reindex` | `analysis-icu`、`repository-s3` |

2025-07-12 11:14:07 314

原创 【Elasticsearch】function_score

如果你希望在 Elasticsearch 查询中降低某些特定 `id` 的文档评分,可以通过 `function_score` 查询结合 `script_score` 函数来实现。3. 使用 Elasticsearch 的 `ingest pipeline`:在数据索引时,通过 Elasticsearch 的 `ingest pipeline` 对数据进行预处理,例如从外部系统获取数据并存储到文档中。我们希望降低某些特定 `id` 的文档评分,例如 `id` 为 `1` 和 `id` 为 `3` 的文档。

2025-07-09 09:01:07 482

原创 编码器(Encoder)和解码器(Decoder)

预训练模型的基础能力:预训练模型(如 BERT、Word2Vec、Doc2Vec 等)在大规模通用语料上进行了训练,已经学习到了语言的基本模式和语义信息。例如,BERT 通过掩码语言模型(MLM)和下一句预测(NSP)任务进行预训练,目的是让模型能够理解输入文本的语义和上下文关系。例如,GPT 系列和 LLaMA 通过自回归语言模型任务进行预训练,目的是让模型能够根据输入的向量生成高质量的文本。例如,对生成的向量进行降维(如 PCA 或 t-SNE)、归一化等操作,以提高向量的可区分性和一致性。

2025-07-08 22:46:04 999

原创 【Elasticsearch】refresh与提交

写入Lucene段:刷新操作会将内存中的索引缓冲区(Index Buffer)中的数据写入到Lucene的倒排索引中,并创建一个新的Lucene段(Segment)。- 合并数据:提交操作会将Translog中的操作与文件系统缓存中的Lucene段进行合并,确保所有未提交的操作都被持久化。- 提交操作会将Translog中的操作与文件系统缓存中的Lucene段进行合并,确保所有未提交的操作都被持久化。- 提交操作会将文件系统缓存中的Lucene段完全写入到磁盘中,并创建一个新的Lucene提交点。

2025-07-03 11:26:16 388

原创 【Elasticsearch】自定义相似性算法

Elasticsearch 默认使用 BM25 算法,但也可以切换到其他内置的相似度算法,如 TF-IDF 或布尔相似度。通过以上方法,可以根据具体需求自定义 Elasticsearch 的相似度算法,以优化搜索结果的相关性。如果内置算法无法满足需求,可以通过脚本自定义相似度算法。- 如果需要调整已有索引的相似度算法,可以通过关闭索引、更新设置、重新开启索引的方式进行。- 自定义相似度算法需要在创建索引时指定,无法直接修改已有字段的相似度算法。3. 使用脚本自定义相似度算法。1. 使用内置相似度算法。

2025-06-19 11:00:56 353

原创 【Elasticsearch】TF-IDF 和 BM25相似性算法

在 Elasticsearch 中,TF-IDF 和 BM25 是两种常用的文本相似性评分算法,但它们的实现和应用场景有所不同。- 定义与原理:BM2 是5对 TF-IDF 的改进,引入了更多因素,如文档长度归一化和词频饱和度处理。- 如果你的文档集合较小,或者对性能要求极高且对文档长度不敏感,可以考虑使用 TF-IDF。- 如果你的应用场景对文档长度敏感,或者需要更灵活的评分调整,建议使用 BM25。- 不考虑文档长度和查询长度的影响,可能导致长文档评分偏低。- 忽视语义,将文档视为词袋模型,忽略词序。

2025-06-19 10:59:09 395

原创 【Elasticsearch】优化点

语义搜索:利用Elasticsearch的语义搜索功能(如`text`字段的`match`查询结合`synonyms`分析器),理解用户问题的语义,而不仅仅是关键词匹配。- 权重调整:通过调整字段权重(`boosting`查询或`function_score`查询),提高某些字段(如条文标题)的权重,使搜索结果更符合用户需求。- 布尔查询:使用布尔查询(`bool`)结合`must`、`should`、`filter`等子句,实现更复杂的查询逻辑,例如同时满足多个条件的条文。

2025-06-18 13:59:26 284

原创 【Elasticsearch】search_after不支持随机到哪一页,只能用于上一页或下一页的场景

如果需要跳转到任意一页,`search_after` 无法直接实现,因为它无法像 `from` 和 `size` 那样通过偏移量直接定位到目标页。`search_after` 确实不支持随机访问(即直接跳到任意一页),因此在前端需要随机跳转到某一页的场景中,使用 `search_after` 是不合适的。根据你的描述,如果前端允许用户随意点击某一页,那么确实不适合使用 `search_after`,而应该使用 `from` 和 `size` 来实现分页功能。- 不支持随机访问,用户不能直接跳转到任意一页。

2025-06-03 09:23:51 805

原创 【ClickHouse】RollingBitmap

ClickHouse 的 RollingBitmap 是一种基于 Bitmap 的数据结构,用于高效处理数据的动态变化和时间窗口计算。RollingBitmap 的核心思想是将数据按时间窗口切分,每个窗口对应一个 Bitmap,通过滚动窗口的方式动态更新 Bitmap 数据。- 对于一个 30 天的滚动窗口,每天生成一个新的 Bitmap,同时移除最早一天的 Bitmap,从而实现数据的动态更新。1. 高效的时间窗口计算:通过滚动窗口的方式,可以快速计算任意时间范围内的数据,而无需重新扫描整个数据集。

2025-05-30 10:23:03 422

原创 【Elasticsearch】suggest_mode

suggest_mode` 是 Elasticsearch 中 `term suggester` 和 `phrase suggester` 的一个参数,用于控制建议的生成方式。3. `always`:无论输入的词是否存在于索引中,都会提供建议。这种模式会为所有输入的词生成建议,无论它们是否已经存在于索引中。2. `popular`:仅建议在比原始建议文本术语出现频率更高的词。通过 `suggest_mode` 参数,可以根据实际需求调整建议的生成策略,从而优化用户体验和建议的相关性。

2025-05-30 09:40:13 668

原创 【Elasticsearch】suggest

通过 `term suggest`、`phrase suggest`、`completion suggest` 和 `context suggest`,你可以实现拼写纠错、短语建议、自动补全和上下文过滤等功能。在Elasticsearch中,`suggest` 是一个非常强大的功能,用于实现自动补全、拼写纠错和模糊搜索等功能。`phrase suggest` 可以根据用户的输入提供完整的短语建议。`context suggest` 可以结合上下文信息(如分类、标签等)提供更精准的建议。

2025-05-29 17:33:01 1088

原创 【Elasticsearch】exists` 查询用于判断文档中是否存在某个指定字段。它检查字段是否存在于文档中,并且字段的值不为 `null`

这个查询会返回第一个文档(`product_id` 为 `1`),因为它的 `category` 字段存在且值为 `"electronics"`。- 第一个文档(`product_id` 为 `1`),因为它的 `category` 字段存在且值为 `"electronics"`。- 不会返回第二个文档(`product_id` 为 `2`),因为它的 `category` 字段值为 `null`。- 不会返回第三个文档(`product_id` 为 `3`),因为它的 `category` 字段不存在。

2025-05-29 15:09:29 540

原创 【Elasticsearch】track_total_hits

在 Elasticsearch 中,`track_total_hits` 是一个查询参数,用于控制是否精确计算搜索结果的总命中数(`total hits`)。从 Elasticsearch 7.0 开始,`track_total_hits` 参数被引入,以提供更灵活的控制。如果你对总命中数的精确性要求不高,可以将 `track_total_hits` 设置为 `false`,以提高查询性能。如果你需要精确的总命中数,无论结果集大小如何,可以将 `track_total_hits` 设置为 `true`。

2025-05-28 11:04:37 593

原创 【Elasticsearch】控制搜索结果中字段的返回方式

fields` 参数可以用于返回指定的字段值,但需要注意,该参数在较新的版本中已被 `_source` 替代,不过仍然可以使用。`_source` 参数用于控制是否返回 `_source` 字段中的原始 JSON 数据,以及指定需要返回的字段。`stored_fields` 参数用于返回在索引映射中设置为 `store: true` 的字段。- `fields` 参数在旧版本中使用,但已被 `_source` 替代。`inner_hits` 参数用于在嵌套查询中返回嵌套字段的匹配结果。

2025-05-28 07:58:56 417

原创 【Elasticsearch】stored_fields

默认情况下,Elasticsearch 在索引文档时会将所有字段存储在 `_source` 中,而 `_source` 是一个 JSON 格式的字段,包含了完整的文档内容。如果字段没有被存储(`store: false`),则无法通过 `stored_fields` 返回,只能通过 `_source` 获取。- 优化性能:如果只需要检索文档中的某些字段,而不是整个 `_source`,设置 `stored_fields` 可以减少数据传输量,从而提高检索性能。因此,需要根据实际需求合理选择存储的字段。

2025-05-28 07:53:07 566

原创 【Elasticsearch】ingest对于update操作起作用吗?

单条更新:在使用 Update API 进行单条文档更新时,可以通过指定 `pipeline` 参数来应用 Ingest Pipeline。- 批量更新:在使用 `_update_by_query` API 批量更新文档时,也可以结合 Ingest Pipeline。- 性能影响:Ingest Pipeline 的使用会增加一定的处理时间,尤其是在批量更新时。这样在更新文档的同时,Ingest Pipeline 会对更新后的文档进行处理。Ingest Pipeline 在 Update 操作中的应用。

2025-05-27 16:41:46 445

原创 【Elasticsearch】retry_on_conflict

在 Elasticsearch 中,`retry_on_conflict` 是 `_update` 和 `_update_by_query` API 的一个参数,用于处理并发冲突。- `retry_on_conflict`:一个整数值,表示在遇到版本冲突时,Elasticsearch 将重试更新操作的次数。- 高并发环境:在多用户同时更新同一个文档的场景中,`retry_on_conflict` 可以减少因版本冲突导致的更新失败。批量更新(`_update_by_query` API)

2025-05-27 10:01:52 487

原创 【Elasticsearch】_update api用于更新单文档,更新多个文档使用_update_by_query

脚本更新:通过 `script` 参数,可以使用脚本动态更新文档内容,甚至在文档不存在时创建新文档(通过 `scripted_upsert`)。如果你需要更新多个文档,可以使用 `_update_by_query` API,它允许你根据查询条件批量更新文档。- 单文档操作:`_update` API 一次只能操作一个文档,通过指定文档的 `_id` 来定位目标文档。- `_update_by_query` API:适用于批量更新,可以根据查询条件更新多个文档。`_update` API 的特点。

2025-05-27 09:59:58 423

原创 【Elasticsearch】使用脚本删除索引中的某个字段

`ctx._source.remove('field_to_delete')`:从文档中删除字段 `field_to_delete`。- `_update_by_query` 和 `_reindex` 操作可能会对集群性能产生较大影响,尤其是在处理大量数据时。- `query`:指定查询条件,这里使用 `exists` 查询来查找包含字段 `field_to_delete` 的文档。如果你需要删除多个字段,或者需要更复杂的逻辑,可以使用 `_reindex` API 重建索引,并在重建过程中删除字段。

2025-05-27 09:58:23 614

原创 【Elasticsearch】scripted_upsert

在 Elasticsearch 中,`scripted_upsert` 是一个用于更新操作的参数,它允许在文档不存在时通过脚本初始化文档内容,而不是直接使用 `upsert` 部分的内容。当设置 `scripted_upsert` 为 `true` 时,Elasticsearch 会根据脚本逻辑来处理文档的创建和更新,而不是直接使用 `upsert` 部分的内容。- `upsert` 部分:即使设置了 `scripted_upsert`,`upsert` 部分仍然需要提供一个空对象 `{}`,否则会报错。

2025-05-27 09:55:59 532

原创 【Elasticsearch】更新操作原理

Elasticsearch 的更新操作(如 `_update` 和 `_update_by_query`)在底层实现上有一些复杂的原理,这些原理涉及到 Elasticsearch 的数据存储机制、索引机制以及事务日志(Translog)的使用。- 在更新操作时,可以指定 `if_seq_no` 和 `if_primary_term` 参数,以确保只有在文档的序列号和主版本号匹配时才执行更新。- 异步处理:某些更新操作(如 `_flush` 和 `_refresh`)是异步执行的,以减少对请求的阻塞。

2025-05-27 09:44:25 429

原创 【Elasticsearch】PUT` 请求覆盖式更新

当你使用 `PUT` 请求向索引中写入文档时,如果文档已经存在,Elasticsearch 会完全替换整个文档的内容,而不是进行部分更新。如果文档的序列号(`seq_no`)或主版本号(`primary_term`)与提供的值不匹配,Elasticsearch 将拒绝此次更新操作,从而避免覆盖其他用户的更改。- 完全替换文档:当你需要更新文档的大部分内容,或者完全重新定义文档时,`PUT` 是一个合适的选择。- 文档不存在时:`PUT` 请求会创建一个新的文档,并使用提供的 JSON 数据作为文档内容。

2025-05-27 09:34:52 470

原创 【Elasticsearch】_update api的增量更新

当你使用 `_update` API 时,Elasticsearch 会将你提供的更新内容(`doc` 部分)与现有文档进行合并,而不是完全替换整个文档。- `doc_as_upsert` 参数:如果设置了 `doc_as_upsert`,并且文档不存在,`doc` 部分的内容将被用作新文档的完整内容。是的,Elasticsearch 的 `_update` API 支持增量更新。总之,Elasticsearch 的 `_update` API 提供了灵活的增量更新功能,非常适合需要部分更新文档的场景。

2025-05-27 09:29:15 433

原创 【Elasticsearch】doc_as_upsert

在Elasticsearch中,`doc_as_upsert` 是一个用于更新文档的参数,它与 `_update` API 结合使用,用于实现“文档不存在则插入,存在则更新”的功能。- `doc_as_upsert` 参数:当设置为 `true` 时,如果目标文档不存在,`doc` 部分的内容将被用作插入的新文档内容。- 数据一致性:使用 `doc_as_upsert` 时,需要确保 `doc` 部分的内容是完整的,因为这将作为新文档的内容。`doc_as_upsert` 的含义。

2025-05-27 09:21:25 473

原创 【Elasticsearch】调用_flush api会调用_refresh 吗?

在 Elasticsearch 中,`_flush` 操作的目的是将内存中的数据和事务日志(translog)中的操作持久化到磁盘。为了确保数据的一致性和完整性,在 `_flush` 操作开始之前,Elasticsearch 会先执行 `_refresh` 操作,将内存缓冲区中的数据写入到新的 Lucene segment 中并加载到文件系统缓存中。调用 `_flush` API 时,Elasticsearch 会先执行 `_refresh` 操作,以确保数据在持久化到磁盘之前已经处于可搜索的状态。

2025-05-27 09:09:30 553

原创 【Elasticsearch】`_refresh`和`_flush`的区别

性能影响:`_refresh`操作的开销相对较小,但频繁的`_refresh`可能会影响写入性能;- `_flush`操作会先执行`_refresh`,将内存缓冲区中的数据写入新的Lucene segment并加载到文件系统缓存中。- 操作范围:`_refresh`操作主要涉及内存缓冲区和文件系统缓存,而`_flush`操作会将数据写入磁盘并清空事务日志。- 数据可见性:`_refresh`使数据在搜索中可见,而`_flush`主要用于数据的持久化,不影响数据的搜索可见性。- 每30分钟定时触发。

2025-05-27 09:05:23 620

原创 IntelliJ IDEA 中配置 Gradle 的分发方式distribution

Gradle Wrapper 的配置文件是 `gradle-wrapper.properties`,位于项目的 `gradle/wrapper` 目录中。- 你可以在 IDEA 的设置中选择使用 Gradle Wrapper,IDEA 会根据 `gradle-wrapper.properties` 文件中的配置自动处理 Gradle 的下载和使用。如何在 IntelliJ IDEA 中配置 Gradle 的分发方式,包括使用 Gradle Wrapper 或本地安装的 Gradle。

2025-05-25 19:35:03 504

原创 【Elasticsearch】创建别名的几种方式

可以通过 `_aliases` API 动态地将别名从一个索引切换到另一个索引,这种方式可以在零停机的情况下完成索引的切换。在创建索引时,可以直接在索引定义中指定别名。这种方式可以在索引创建的同时完成别名的绑定,避免后续的额外操作。可以同时为多个索引创建同一个别名,这种方式常用于查询多个索引时使用统一的别名。如果索引已经存在,可以通过 `_aliases` API 为索引添加别名。在创建别名时,可以指定某个索引为写入索引,这种方式常用于读写分离的场景。1. 在创建索引时指定别名。4. 为多个索引创建别名。

2025-05-23 13:52:59 630

原创 【Elasticsearch】给所索引创建多个别名

比如,旧索引是`index_v1`,别名为`current_index`,当创建了新索引`index_v2`后,可以将`current_index`别名从`index_v1`切换到`index_v2`,应用程序无需感知底层索引的变化。- 比如,有多个按日期分片的索引`log_202501`、`log_202502`等,可以创建一个别名`all_logs`,将查询请求发送到`all_logs`别名,Elasticsearch 会自动将查询路由到所有相关的索引。为什么可以创建多个别名。

2025-05-23 13:49:25 466

xampp配置.doc

xampp配置xampp配置xampp配置xampp配置xampp配置xampp配置xampp配置xampp配置xampp配置xampp配置xampp配置xampp配置xampp配置xampp配置

2018-04-25

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除