把心事存进鸿蒙:ArkTS 为日记本设计长文本表与时间戳字段
实例电子日记本Diary技术长文本存储、时间分组查询、关键词搜索一、业务需求分析日记本的数据形态与记账本有何不同前三个实例我们处理了「任务清单」短文本状态、「通讯录」结构化字段和「记账本」数值时间。到了实例 4「电子日记本」数据形态发生了一次质变主体内容从「字段」变成了「长文本」。日记应用的核心业务需求可以归纳为五点写日记标题 正文可能上千字的长文本 心情 天气 地点一次保存按时间轴浏览日记天生是「按时间组织的个人编年史」页面要按日期/月份分组展示时间线是主视觉关键词搜索用户想「找那天写日记提到爬山的记录」需要标题/正文双字段模糊搜索编辑与删除日记写错了要能改、能删轻量统计总篇数、本月篇数支撑页面头部信息。对比记账本日记本的数据特点维度记账本实例 3日记本实例 4主数据金额 REAL 分类 TEXT正文长文本 TEXT时间角色统计维度SUM/GROUP BY组织维度时间轴分组检索方式分类精确匹配关键词 LIKE 模糊更新频率几乎不更新删了重记经常编辑改日记这些差异决定了表结构设计的不同侧重。下面进入字段设计。二、字段设计表每一列都为「时间轴」服务字段名类型约束说明idINTEGERPRIMARY KEY AUTOINCREMENT自增主键titleTEXTNOT NULL标题contentTEXTNOT NULL正文长文本可数千字moodTEXTDEFAULT ‘’心情 emoji…weatherTEXTDEFAULT ‘’天气晴/多云/雨…locationTEXTDEFAULT ‘’地点created_timeINTEGERNOT NULL创建时间戳毫秒updated_timeINTEGERNOT NULL最近修改时间戳毫秒设计要点逐条拆解1. content 用 TEXT 存长文本不需要分表。这是初学者最容易纠结的问题「正文那么长要不要单独建一张 content 表」答案是不需要。SQLite 单条 TEXT 字段可以存数百 MB一篇几千字的日记约 10KB毫无压力。RDB 的设计原则是「一行一个业务实体」——一篇日记就是一行正文是它的一个属性。强行拆表反而增加 JOIN 复杂度得不偿失。2. mood 直接存 emoji 字符。心情用 emoji//而非数字编码。为什么这里不用记账本 type 的 0/1 数字编码因为心情没有「参与计算」的需求——不做 SUM、不做 GROUP BY 统计只有展示。当枚举值只用于展示时直接存可读文本UI 零转换是最务实的方案。判断用数字还是文本的标准这个字段会不会参与聚合运算会如记账本 type就编码成数字不会如心情就存文本。3. location 取代「标签」体系。早期的文章版设计里有tags逗号分隔标签字段落地版将其替换为location地点。原因个人日记场景下「标签」概念偏重而「地点」新家/公司/书房更贴近日记的自然属性也与文章版 4-2 的时间轴节点设计一致。如果你需要标签体系逗号分隔 LIKE 查询的模式可以随时加回来——SQLite 对字符串的处理非常灵活。4. created_time 与 updated_time 双时间戳。这是内容型应用的标准配置created_time创建时刻永不变更updated_time每次编辑刷新时间轴排序用它——「最近修改的日记排前面」比「最早写的排前面」更符合用户心智刚编辑完的日记大概率还想继续看。5. 为什么只给 created_time 建索引落地版的建表 SQL 为created_time建了idx_diary_time索引排序、按月份LIKE 2025-06%过滤都走它。其实更严谨的做法是索引updated_time排序字段但个人日记几百条数据两者性能差异不可感知选择 created_time 是因为它的值域稳定插入后不变索引不会因频繁更新而失效。这个细节体现了「索引服务于查询」的朴素原则。三、建表 SQL把设计变成现实CREATETABLEIFNOTEXISTSdiary(idINTEGERPRIMARYKEYAUTOINCREMENT,titleTEXTNOTNULL,contentTEXTNOTNULL,moodTEXTDEFAULT,weatherTEXTDEFAULT,locationTEXTDEFAULT,created_timeINTEGERNOTNULL,updated_timeINTEGERNOTNULL);CREATEINDEXIFNOTEXISTSidx_diary_timeONdiary(created_time);注意三点IF NOT EXISTS幂等重复执行不报错这是 getStore 里建表语句的统一要求DEFAULT mood 有默认值插入时可以省略代码更简洁NOT NULL DEFAULT ‘’weather、location 可空但默认空串避免 NULL 泄漏到 UI 层页面|| 兜底是双保险。四、DiaryDao 封装把 SQL 关进类里数据层核心是DiaryDao职责边界与前面实例一致只管数据库不管 UI。先看实体接口exportinterfaceDiary{id:number;title:string;content:string;// 长文本正文mood:string;// 心情 emoji…weather:string;// 天气晴/多云/雨…location:string;// 地点createdTime:number;// 日记时间戳毫秒updatedTime:number;}字段命名依然是「DB 蛇形 ↔ 代码驼峰」的双风格映射集中在rowToDiary方法privatestaticrowToDiary(result:relationalStore.ResultSet):Diary{return{id:result.getLong(result.getColumnIndex(id)),title:result.getString(result.getColumnIndex(title)),content:result.getString(result.getColumnIndex(content)),mood:result.getString(result.getColumnIndex(mood))||,weather:result.getString(result.getColumnIndex(weather))||,location:result.getString(result.getColumnIndex(location))||,createdTime:result.getLong(result.getColumnIndex(created_time)),updatedTime:result.getLong(result.getColumnIndex(updated_time)),};}与文章版代码的关键差异这是本实例读者最容易踩的坑文章版用row: relationalStore.ValuesBucketrow.id as number强转落地版改用ResultSetgetColumnIndexgetLong/getString——前者拿到的getRow()是弱类型的键值容器强转不安全后者类型安全、NULL 可兜底。文章版静态方法里写this.store落地版一律DiaryDao.store——ArkTS 禁止静态上下文使用thisarkts-no-this-in-static。文章版 context 用common.UIAbilityContext落地版统一common.Context基类复用性更强。getStore单例复用模式不变staticasyncgetStore(context:common.Context):PromiserelationalStore.RdbStore{if(DiaryDao.store){returnDiaryDao.store;}constconfig:relationalStore.StoreConfig{name:diary.db,securityLevel:relationalStore.SecurityLevel.S1,};DiaryDao.storeawaitrelationalStore.getRdbStore(context,config);// 建表 建索引见上节 SQLhilog.info(DOMAIN,TAG,日记表初始化成功);returnDiaryDao.store;}五、核心 CRUD写、查、改、删插入写日记staticasyncinsert(context:common.Context,d:Diary):Promisenumber{conststoreawaitDiaryDao.getStore(context);constvalues:relationalStore.ValuesBucket{title:d.title,content:d.content,mood:d.mood,weather:d.weather,location:d.location,created_time:d.createdTime,updated_time:d.updatedTime,};returnawaitstore.insert(DiaryDao.TABLE,values);}注意content作为字符串直接塞进 ValuesBucket——长文本无需特殊处理SQLite 自动分配存储这是 TEXT 类型的天然优势。全部日记按修改时间倒序staticasyncqueryAll(context:common.Context):PromiseDiary[]{conststoreawaitDiaryDao.getStore(context);constpredicatesnewrelationalStore.RdbPredicates(DiaryDao.TABLE);predicates.orderByDesc(created_time);constresultawaitstore.query(predicates);returnDiaryDao.collect(result);}排序字段用created_time与索引一致页面时间轴按创建时间分组展示语义上更符合「日记编年史」。更新编辑日记刷新 updated_timestaticasyncupdate(context:common.Context,d:Diary):Promisenumber{conststoreawaitDiaryDao.getStore(context);constvalues:relationalStore.ValuesBucket{title:d.title,content:d.content,mood:d.mood,weather:d.weather,location:d.location,updated_time:d.updatedTime,};constpredicatesnewrelationalStore.RdbPredicates(DiaryDao.TABLE);predicates.equalTo(id,d.id);returnawaitstore.update(values,predicates);}注意 update 不更新created_time——创建时间不可变只刷updated_time这是双时间戳的协作方式。删除与计数staticasyncdelete(context:common.Context,id:number):Promisenumber{conststoreawaitDiaryDao.getStore(context);constpredicatesnewrelationalStore.RdbPredicates(DiaryDao.TABLE);predicates.equalTo(id,id);returnawaitstore.delete(predicates);}staticasynccount(context:common.Context):Promisenumber{conststoreawaitDiaryDao.getStore(context);constresultawaitstore.querySql(SELECT COUNT(*) AS c FROM${DiaryDao.TABLE});lettotal0;if(result.goToNextRow()){totalresult.getLong(result.getColumnIndex(c));}result.close();returntotal;}六、时间分组查询按月份捞日记时间轴页面的核心需求选中某个月份只看那个月的日记。落地版提供queryByMonthstaticasyncqueryByMonth(context:common.Context,month:string):PromiseDiary[]{conststoreawaitDiaryDao.getStore(context);constpredicatesnewrelationalStore.RdbPredicates(DiaryDao.TABLE);predicates.like(created_time,${month}%).orderByDesc(created_time);constresultawaitstore.query(predicates);returnDiaryDao.collect(result);}这个方法的巧妙之处like(created_time, 2025-06%)用 LIKE 前缀匹配模拟「时间范围查询」。因为 created_time 存的是毫秒时间戳的字符串形式——不对等等created_time 是 INTEGER 类型LIKE 匹配的是数字的字符串表示。2025-06-01 00:00:00的时间戳是1748707200000用LIKE 2025-06%匹配不到这是一个需要澄清的坑文章版的queryByMonth按updated_time LIKE的设计在 INTEGER 时间戳上是不成立的那是按文本日期存储时的写法。落地版页面DiaryPage采用更可靠的方式直接queryAll拉全量在内存里按fmtDate分组渲染时间轴节点。个人日记数据量小几十上百篇全量加载 前端分组是务实的选择若数据量大正确做法是between(startOfMonth, endOfMonth)毫秒区间查询——这与记账本实例的区间查询一脉相承。关键词搜索标题/正文双字段 LIKEstaticasyncsearch(context:common.Context,keyword:string):PromiseDiary[]{conststoreawaitDiaryDao.getStore(context);constpredicatesnewrelationalStore.RdbPredicates(DiaryDao.TABLE);predicates.like(title,%${keyword}%).or().like(content,%${keyword}%).orderByDesc(created_time);constresultawaitstore.query(predicates);returnDiaryDao.collect(result);}LIKE %关键词%是包含匹配——标题或正文任意位置出现关键词即命中。.or()把两个条件连接为 OR 语义。注意LIKE 前导%会导致索引失效无法走 B 树全表扫描但日记本几百条数据扫描无压力。如果将来数据量到十万级应改用 FTS5 全文索引——那是另一个维度的优化本书暂不展开。七、技术要点对照表技术点实现方式生产价值长文本TEXT 字段直接存正文无需分表读写简单双时间戳created_time updated_time创建/编辑分离时间轴按编辑排序关键词搜索title/content OR LIKE双字段命中率高时间分组全量加载 前端按日期分组小数据量下的务实方案emoji 存储mood 直接存字符UI 零转换幂等建表CREATE IF NOT EXISTS重复启动不报错八、文章小结日记本数据层与记账本的数值聚合完全不同重心在长文本存储策略 双时间戳的时间轴组织 LIKE 关键词检索。TEXT 类型让长正文毫无负担双时间戳让「最近编辑优先」成为可能LIKE 让搜索零配置。下一篇4-2将展示这些数据如何被时间轴 UI 呈现——垂直时间轴 日期节点 心情天气卡片把数据变成故事。动手练习尝试给search增加第三个条件按天气过滤equalTo(weather, 晴)并观察 OR 与 AND 组合时 RdbPredicates 的链式写法。

相关新闻

Docker Desktop最新版安装踩坑全记录(Windows_Mac_Linux)【2026 4.74.0 终版】

Docker Desktop最新版安装踩坑全记录(Windows_Mac_Linux)【2026 4.74.0 终版】

✅ 适配版本:Docker Desktop 4.74.0(2026最新稳定版) ✅ 适配系统:Windows10/11、Mac Intel/Apple Silicon、Linux 全主流发行版 ✅ 阅读收益:一次性解决99%安装报错、启动失败、镜像超时、环境冲突问题 📝…

2026/8/16 3:51:08 阅读更多 →
率能SS6850H 20V/1A/双通道H桥驱动芯片,零待机电流与ENA使能控制(ESOP8),用于家电/打印机/电机驱动

率能SS6850H 20V/1A/双通道H桥驱动芯片,零待机电流与ENA使能控制(ESOP8),用于家电/打印机/电机驱动

在12V系统电机驱动应用中,封装形式的差异直接影响芯片的散热性能和PCB布局密度。领芯微(LEADPOWER)推出的SS6850H是一款2通道H桥驱动芯片,专为12V系统产品的电机驱动而优化。每个H桥可提供最大1A峰值电流和0.7A均方根电流&#xf…

2026/8/16 3:51:08 阅读更多 →
AI论文写作工具哪个最好?2026亲测

AI论文写作工具哪个最好?2026亲测

"开题报告改5版仍被打回","文献综述堆30篇却毫无逻辑","格式排版耗3天还不符合学校要求","AI生成内容被AIGC检测标红"——2026年高校AI学术规范全面收紧的背景下,毕业生在选择AI论文写作…

2026/8/16 3:51:08 阅读更多 →

最新新闻

UIUC CS225数据结构课程:从C++面向对象到图论算法的工程实践指南

UIUC CS225数据结构课程:从C++面向对象到图论算法的工程实践指南

如果你正在学习数据结构,大概率会遇到这样的困境:教材上的概念看似清晰,但一到动手实现就无从下手;网上教程要么过于简单,要么直接甩给你一堆看不懂的代码;更让人焦虑的是,面试官问的“红黑树旋…

2026/8/16 4:42:20 阅读更多 →
Grok Bot登顶Hacker News:解析实时AI助手的技术架构与开发实践

Grok Bot登顶Hacker News:解析实时AI助手的技术架构与开发实践

最近,如果你关注 AI 和开发者社区,可能会发现一个有趣的现象:一个名为Grok Bot的 AI 聊天机器人,在技术圈的“风向标”网站Hacker News上持续霸榜,热度远超许多知名开源项目或技术新闻。它的背后,是马斯克旗…

2026/8/16 4:42:20 阅读更多 →
企业 AI Agent 监控不止延迟与错误率,为何必须核查推理过程与回答质量?

企业 AI Agent 监控不止延迟与错误率,为何必须核查推理过程与回答质量?

企业 AI Agent 为什么不能只看延迟和错误率,还要评估回答质量和推理过程?从接口监控走向任务级治理在企业 AI Agent 上线落地之后,多数技术团队依旧沿用传统应用的运维监控范式,核心监测维度包含接口返回状态、平均延迟数值、错误…

2026/8/16 4:42:20 阅读更多 →
梦绘片场 ProjectDream角色库与一致性篇:从项目到成片的 AI 漫剧工作台

梦绘片场 ProjectDream角色库与一致性篇:从项目到成片的 AI 漫剧工作台

角色不跑偏:ProjectDream 的角色库、定妆图和声线闭环本文继续记录 ProjectDream 的核心功能模块,这一篇聚焦角色库、角色定妆图和角色一致性控制。一、前言 在 AI 漫剧或短视频项目里,角色一致性通常比“能不能生成”更难处理。 如果同一个角…

2026/8/16 4:42:20 阅读更多 →
Win11下VSCode配置Python虚拟环境:从venv原理到高效开发实战

Win11下VSCode配置Python虚拟环境:从venv原理到高效开发实战

1. 项目概述:为什么在Win11上用VSCode配置Python虚拟环境是开发者的必修课 如果你在Windows 11上写Python,还在用系统全局的Python环境,那无异于在厨房里把所有调料都倒进一个罐子——炒菜时,你永远不知道会尝到什么奇怪的味道。…

2026/8/16 4:41:20 阅读更多 →
OpenClaw文档即工具架构:AI Agent技能系统的扩展性革命

OpenClaw文档即工具架构:AI Agent技能系统的扩展性革命

1. 从一个“反直觉”的架构选择说起如果你关注过一些现代AI应用框架,比如LangChain、Semantic Kernel,你会发现它们都在强调一个概念:工具(Tool)。在这些框架里,工具通常被定义为一个函数,它有明…

2026/8/16 4:41:20 阅读更多 →

日新闻

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

如果你是一名开发者,最近可能已经感受到了AI大模型正在从“玩具”变成“生产力工具”的强烈信号。从代码补全到智能Agent,从本地部署到云端API,我们正处在一个技术栈快速重构的节点。然而,面对层出不穷的模型、框架和工具&#xf…

2026/8/16 0:00:54 阅读更多 →
工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

第四篇:反射——高频能量撞墙之后会发生什么? —— 你以为信号已经过去了,其实它正在回来打你 老Q的现场笔记 第五季,我们正式进入工业神经系统层。这里不再是单个设备的战斗,而是整个工厂“经脉”层面的秩序之战。从这一篇开始,你将第一次看清:看似简单的信号传播,背…

2026/8/16 0:00:55 阅读更多 →
【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和…

2026/8/16 0:03:55 阅读更多 →

周新闻

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

如果你是一名开发者,最近可能已经感受到了AI大模型正在从“玩具”变成“生产力工具”的强烈信号。从代码补全到智能Agent,从本地部署到云端API,我们正处在一个技术栈快速重构的节点。然而,面对层出不穷的模型、框架和工具&#xf…

2026/8/16 0:00:54 阅读更多 →
工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

第四篇:反射——高频能量撞墙之后会发生什么? —— 你以为信号已经过去了,其实它正在回来打你 老Q的现场笔记 第五季,我们正式进入工业神经系统层。这里不再是单个设备的战斗,而是整个工厂“经脉”层面的秩序之战。从这一篇开始,你将第一次看清:看似简单的信号传播,背…

2026/8/16 0:00:55 阅读更多 →
【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和…

2026/8/16 0:03:55 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/14 13:40:53 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/14 14:06:45 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/15 2:35:29 阅读更多 →