Dexie IndexedDB Schema for Caching Articles and Comments in WeChat Article Exporter
The WeChat Article Exporter uses a Dexie IndexedDB database named exporter.wxdown.online with two main tables—article (composite key ${fakeid}:${aid}) and comment (primary key url)—to persistently cache fetched WeChat data client-side.
The wechat-article-exporter is a Nuxt-based open-source tool for archiving WeChat public account content. To eliminate redundant API requests and enable offline browsing, the application implements a client-side caching layer using Dexie.js, a minimalistic IndexedDB wrapper. The schema definition and versioning logic are centralized in store/v2/db.ts, while high-level data access methods reside in store/v2/article.ts and store/v2/comment.ts.
Database Configuration
The IndexedDB instance is initialized as a constant db object with strict TypeScript typing. The database name is hardcoded as exporter.wxdown.online in store/v2/db.ts.
const db = new Dexie('exporter.wxdown.online') as Dexie & {
article: Table<ArticleAsset, string>;
comment: EntityTable<CommentAsset, 'url'>;
// ... other tables
};
The schema undergoes versioned upgrades. Version 1 establishes base tables, while Version 2 adds the fakeid index to the comment table for efficient account-based lookups.
Article Table Schema
The article table stores metadata and content for individual WeChat articles. Its schema is defined across database versions as follows:
- Primary Key: Composite string
`${fakeid}:${aid}`(supplied explicitly during insertion, not auto-generated) - Indexes:
fakeid,create_time,link
// store/v2/db.ts
db.version(1).stores({
article: ', fakeid, create_time, link', // empty slot before comma = manual primary key
});
db.version(2).stores({
article: ', fakeid, create_time, link', // unchanged in v2
});
The empty string before the first comma in the schema declaration indicates Dexie should not auto-increment the primary key; instead, the application supplies the composite key ${fakeid}:${article.aid} when calling db.article.put().
Comment Table Schema
The comment table caches comment threads associated with articles. Unlike the article table, it uses a natural key derived from the comment's URL.
- Primary Key:
url(the absolute URL of the comment resource) - Indexes:
url(v1),fakeid(added in v2)
// store/v2/db.ts
db.version(1).stores({
comment: 'url',
});
db.version(2).stores({
comment: 'url, fakeid', // Enables filtering comments by public account
});
The addition of the fakeid index in Version 2 allows the application to query all comments belonging to a specific public account without scanning the entire table.
Programmatic Usage
The repository provides strongly-typed helper functions in store/v2/article.ts and store/v2/comment.ts to interact with these tables.
Inserting or Updating Articles
To cache an article, generate the composite primary key and call put() with the key as the second argument:
import { db } from '@/store/v2/db';
import type { ArticleAsset } from '@/store/v2/article';
async function cacheArticle(fakeid: string, article: ArticleAsset) {
const primaryKey = `${fakeid}:${article.aid}`;
await db.article.put(
{ ...article, fakeid, _status: '' },
primaryKey
);
}
This pattern is implemented in store/v2/article.ts around lines 29–31.
Querying Articles by Account
Retrieve articles for a specific public account (fakeid) created before a timestamp, sorted newest-first:
async function getArticlesBefore(fakeid: string, createTime: number) {
return db.article
.where('fakeid')
.equals(fakeid)
.and(a => a.create_time < createTime)
.reverse()
.sortBy('create_time');
}
This query leverages the fakeid and create_time compound indexes defined in the schema.
Caching Comments
Storing comments requires no manual key generation because url is defined as the primary key in the Dexie schema:
import { db } from '@/store/v2/db';
import type { CommentAsset } from '@/store/v2/comment';
async function cacheComment(comment: CommentAsset) {
await db.comment.put(comment); // Primary key is comment.url
}
See store/v2/comment.ts lines 14–18 for the reference implementation.
Retrieving Comments by URL
Fetch a single cached comment using its natural key:
async function getComment(url: string) {
return db.comment.get(url);
}
This operation performs a direct primary key lookup in IndexedDB.
Summary
- The Dexie IndexedDB schema is defined in
store/v2/db.tsand uses the database nameexporter.wxdown.online. - Article records use a composite primary key
`${fakeid}:${aid}`and are indexed onfakeid,create_time, andlink. - Comment records use the comment
urlas the primary key; Version 2 adds afakeidindex for account-scoped queries. - Always provide the composite key explicitly when calling
db.article.put()to avoid auto-increment collisions. - Query performance relies on Dexie's
where()clauses targeting the defined indexes rather than full-table scans.
Frequently Asked Questions
Why does the article table use a composite primary key instead of an auto-incrementing ID?
The application manually constructs the primary key as `${fakeid}:${aid}` to ensure uniqueness across different WeChat public accounts while maintaining a deterministic lookup mechanism. This composite key guarantees that re-fetching the same article from the WeChat API overwrites the existing cache entry rather than creating a duplicate, as implemented in store/v2/article.ts.
What changed between schema Version 1 and Version 2?
Version 2 added the fakeid index to the comment table ('url, fakeid'), whereas Version 1 only indexed the url field. This change enables efficient retrieval of all comments belonging to a specific public account using db.comment.where('fakeid').equals(...), which was not performantly possible in Version 1.
How does Dexie handle the empty string in the article schema definition?
In Dexie schema notation, an empty string before the first comma (as seen in ', fakeid, create_time, link') signals that the primary key is not auto-generated. The application must supply the primary key explicitly during put() or add() operations. If omitted, Dexie would throw an error requiring the key parameter.
Can I query articles without knowing the fakeid?
No. The current schema requires the fakeid (public account identifier) to construct the primary key and to use the fakeid index. To query across all accounts, you would need to perform a full table scan using db.article.toArray(), which is discouraged for performance reasons on large datasets.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →