Parse Server 数据库配置详解:MongoDB 与 PostgreSQL 适配方案
引言
你还在为 Parse Server 数据库选型烦恼吗?MongoDB 和 PostgreSQL 哪个更适合你的项目需求?本文将从架构设计、配置步骤、性能对比三个维度,帮助你快速掌握两种数据库的适配方案,让你的后端存储选择不再纠结。读完本文,你将能够:
- 理解 Parse Server 数据库抽象层的工作原理
- 掌握 MongoDB 和 PostgreSQL 的配置方法
- 根据业务场景选择合适的数据库方案
- 优化数据库连接和查询性能
数据库架构设计
Parse Server 采用适配器模式实现了数据库抽象层,通过统一的接口支持多种数据库后端。核心架构包含以下组件:
存储适配器接口
src/Adapters/Storage/StorageAdapter.js 定义了统一的数据库操作接口,所有数据库适配器都必须实现这些方法。主要包括:
export interface StorageAdapter {
// 类操作
classExists(className: string): Promise<boolean>;
createClass(className: string, schema: SchemaType): Promise<void>;
// 对象操作
createObject(className: string, schema: SchemaType, object: any): Promise<any>;
find(className: string, schema: SchemaType, query: QueryType, options: QueryOptions): Promise<[any]>;
// 索引管理
ensureIndex(className: string, schema: SchemaType, fieldNames: string[]): Promise<any>;
ensureUniqueness(className: string, schema: SchemaType, fieldNames: Array<string>): Promise<void>;
// 事务支持
createTransactionalSession(): Promise<any>;
commitTransactionalSession(transactionalSession: any): Promise<void>;
}
适配器实现
目前 Parse Server 提供了两种官方数据库适配器:
- MongoDB 适配器:src/Adapters/Storage/Mongo/MongoStorageAdapter.js
- PostgreSQL 适配器:src/Adapters/Storage/Postgres/PostgresStorageAdapter.js
这两种适配器都遵循相同的接口规范,但针对不同数据库的特性进行了优化实现。
MongoDB 配置方案
MongoDB 是 Parse Server 的传统默认数据库,提供了灵活的文档存储能力,适合快速开发和迭代。
基本配置
通过 databaseURI 配置项指定 MongoDB 连接信息,格式如下:
const ParseServer = require('parse-server').ParseServer;
const api = new ParseServer({
databaseURI: 'mongodb://username:password@host:port/database?options',
// 其他配置...
});
配置选项在 src/Options/Definitions.js 中有详细定义,主要包括:
module.exports.ParseServerOptions = {
databaseURI: {
env: 'PARSE_SERVER_DATABASE_URI',
help: 'The full URI to your database. Supported databases are mongodb or postgres.',
required: true,
default: 'mongodb://localhost:27017/parse',
},
collectionPrefix: {
env: 'PARSE_SERVER_COLLECTION_PREFIX',
help: 'A collection prefix for the classes',
default: '',
},
// 其他配置...
};
高级配置
MongoDB 适配器提供了多种高级配置选项,可通过 databaseOptions 参数设置:
new ParseServer({
databaseURI: 'mongodb://localhost:27017/parse',
databaseOptions: {
// 连接池大小
poolSize: 10,
// 读取偏好
readPreference: 'secondaryPreferred',
// 连接超时
connectTimeoutMS: 30000,
// 最大连接时间
maxTimeMS: 30000,
// 启用架构钩子
enableSchemaHooks: true,
// 模式缓存 TTL
schemaCacheTtl: 300000
}
});
这些选项在 src/Adapters/Storage/Mongo/MongoStorageAdapter.js 的构造函数中处理:
constructor({ uri = defaults.DefaultMongoURI, collectionPrefix = '', mongoOptions = {} }: any) {
this._uri = uri;
this._collectionPrefix = collectionPrefix;
this._mongoOptions = { ...mongoOptions };
// 处理特定选项
this._maxTimeMS = mongoOptions.maxTimeMS;
this.enableSchemaHooks = !!mongoOptions.enableSchemaHooks;
this.schemaCacheTtl = mongoOptions.schemaCacheTtl;
// 移除不支持的选项
for (const key of ['enableSchemaHooks', 'schemaCacheTtl', 'maxTimeMS']) {
delete mongoOptions[key];
delete this._mongoOptions[key];
}
}
数据类型映射
MongoDB 适配器负责将 Parse 对象转换为 MongoDB 文档格式,主要通过 src/Adapters/Storage/Mongo/MongoTransform.js 中的工具函数实现:
// 对象转换示例
export function parseObjectToMongoObjectForCreate(className: string, object: Object, schema: SchemaType): Object {
const mongoObject = { ...object };
// 处理特殊字段
if (mongoObject.ACL) {
mongoObject._rperm = getReadPermissions(mongoObject.ACL);
mongoObject._wperm = getWritePermissions(mongoObject.ACL);
delete mongoObject.ACL;
}
// 转换字段类型
for (const fieldName in schema.fields) {
const field = schema.fields[fieldName];
if (field.type === 'Pointer' && mongoObject[fieldName]) {
mongoObject[`_p_${fieldName}`] = transformPointer(mongoObject[fieldName]);
delete mongoObject[fieldName];
}
}
return mongoObject;
}
PostgreSQL 配置方案
PostgreSQL 适配器提供了关系型数据库支持,适合需要强事务保证和复杂查询的场景。
基本配置
PostgreSQL 的配置方式与 MongoDB 类似,只需更改 databaseURI 的格式:
new ParseServer({
databaseURI: 'postgres://username:password@host:port/database?options',
// 其他配置...
});
PostgreSQL 适配器在 src/Adapters/Storage/Postgres/PostgresStorageAdapter.js 中实现,支持标准的 PostgreSQL 连接字符串格式。
数据类型映射
PostgreSQL 作为关系型数据库,需要将 Parse 的灵活 schema 映射到关系型表结构。适配器使用 JSONB 类型存储复杂对象,实现了类似文档数据库的灵活性:
const parseTypeToPostgresType = type => {
switch (type.type) {
case 'String':
return 'text';
case 'Date':
return 'timestamp with time zone';
case 'Object':
return 'jsonb';
case 'Boolean':
return 'boolean';
case 'Pointer':
return 'text';
case 'Number':
return 'double precision';
case 'GeoPoint':
return 'point';
case 'Array':
if (type.contents && type.contents.type === 'String') {
return 'text[]';
} else {
return 'jsonb';
}
// 其他类型映射...
default:
throw `no type for ${JSON.stringify(type)} yet`;
}
};
查询转换
PostgreSQL 适配器需要将 Parse 查询转换为 SQL 查询,这一过程在 src/Adapters/Storage/Postgres/PostgresStorageAdapter.js 中实现:
const buildWhereClause = ({ schema, query, index, caseInsensitive }): WhereClause => {
const patterns = [];
let values = [];
const sorts = [];
schema = toPostgresSchema(schema);
for (const fieldName in query) {
// 处理各种查询操作符...
if (fieldValue.$gt !== undefined || fieldValue.$lt !== undefined) {
for (const op of ['$gt', '$lt', '$gte', '$lte']) {
if (fieldValue[op] !== undefined) {
patterns.push(`$${index}:name ${ParseToPosgresComparator[op]} $${index + 1}`);
values.push(fieldName, fieldValue[op]);
index += 2;
}
}
}
// 处理其他查询条件...
}
return {
pattern: patterns.join(' AND '),
values,
sorts
};
};
数据库方案对比
功能对比
| 特性 | MongoDB | PostgreSQL |
|---|---|---|
| 数据模型 | 文档模型 | 关系模型+JSONB |
| 事务支持 | 支持(4.0+) | 完全支持 |
| 索引类型 | B树、哈希、地理空间等 | B树、GiST、GIN等 |
| 查询能力 | MongoDB查询语言 | SQL+JSON函数 |
| 扩展性 | 水平扩展 | 垂直+有限水平扩展 |
| 全文搜索 | 基本支持 | 高级全文搜索 |
| 地理空间查询 | 支持 | 支持(PostGIS) |
性能对比
在不同场景下,两种数据库表现各有优势:
-
写性能:MongoDB 通常在简单写入场景下表现更好,因其文档模型减少了关联操作。
-
读性能:
- 简单查询:两者性能相近
- 复杂关联查询:PostgreSQL 更优
- JSON 操作:PostgreSQL 的 JSONB 性能通常优于 MongoDB
-
索引性能:
- MongoDB 对频繁更新的字段索引维护更高效
- PostgreSQL 的 GIN 索引对 JSONB 和数组类型查询更高效
适用场景
选择 MongoDB 当:
- 需要灵活的 schema 设计
- 开发速度优先于严格的数据一致性
- 主要进行简单的 CRUD 操作
- 需要快速水平扩展
选择 PostgreSQL 当:
- 需要强事务保证
- 有复杂的查询和报表需求
- 需要全文搜索功能
- 数据结构相对固定
- 需要与其他关系型数据库集成
配置示例
MongoDB 配置示例
const ParseServer = require('parse-server').ParseServer;
const server = new ParseServer({
appId: 'myAppId',
masterKey: 'myMasterKey',
serverURL: 'http://localhost:1337/parse',
databaseURI: 'mongodb://localhost:27017/myapp',
collectionPrefix: 'prod_',
databaseOptions: {
poolSize: 20,
readPreference: 'secondaryPreferred',
connectTimeoutMS: 5000,
enableSchemaHooks: true,
schemaCacheTtl: 300000
},
schema: {
lockSchemas: true,
strict: true
}
});
PostgreSQL 配置示例
const ParseServer = require('parse-server').ParseServer;
const server = new ParseServer({
appId: 'myAppId',
masterKey: 'myMasterKey',
serverURL: 'http://localhost:1337/parse',
databaseURI: 'postgres://user:pass@localhost:5432/myapp',
databaseAdapter: require('parse-server/lib/Adapters/Storage/Postgres/PostgresStorageAdapter'),
databaseOptions: {
maxConnections: 20,
ssl: true,
statement_timeout: 30000
},
schema: {
definitions: require('./schemas')
}
});
最佳实践
连接池配置
合理配置连接池对性能至关重要:
// MongoDB 连接池配置
databaseOptions: {
poolSize: 10, // 根据服务器CPU核心数调整,通常每个核心2-3个连接
minPoolSize: 5,
maxPoolSize: 20,
waitQueueTimeoutMS: 10000
}
// PostgreSQL 连接池配置
databaseOptions: {
maxConnections: 20,
idleTimeoutMillis: 30000
}
索引优化
为常用查询字段创建索引:
// 在 Cloud Code 中创建索引
Parse.Cloud.afterSave('Product', async (request) => {
const schema = new Parse.Schema('Product');
await schema.addIndex('name', { name: 1 }, { unique: true });
await schema.addIndex('category_price', { category: 1, price: -1 });
await schema.save();
});
监控与维护
-
MongoDB 监控:
- 使用 MongoDB Compass 监控性能
- 配置慢查询日志
- 定期运行
db.stats()和db.collection.stats()
-
PostgreSQL 监控:
- 使用 pg_stat_statements 跟踪查询性能
- 配置 auto_explain 记录慢查询
- 定期 VACUUM 和 ANALYZE
总结
Parse Server 的数据库抽象层为开发者提供了灵活选择数据库的能力。MongoDB 和 PostgreSQL 各有优势,选择时应根据项目需求、团队熟悉度和长期维护成本综合考虑。
无论选择哪种数据库,都应:
- 合理配置连接池和缓存
- 为常用查询创建适当索引
- 定期监控和优化性能
- 根据业务增长调整数据库架构
通过本文介绍的配置方法和最佳实践,你可以为 Parse Server 构建高效、可靠的数据存储层,满足不同业务场景的需求。
扩展资源
- 官方文档:README.md
- 变更日志:CHANGELOG.md
- 贡献指南:CONTRIBUTING.md
- 安全最佳实践:SECURITY.md
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



