Parse Server 数据库配置详解:MongoDB 与 PostgreSQL 适配方案

Parse Server 数据库配置详解:MongoDB 与 PostgreSQL 适配方案

【免费下载链接】parse-server parse-community/parse-server: Parse Server 是 Parse 后端云服务的开源版本,允许开发者在自己的服务器上托管一个完全功能的Parse服务,以便继续对现有的Parse应用提供支持或者创建新的Parse应用。 【免费下载链接】parse-server 项目地址: https://gitcode.com/gh_mirrors/pa/parse-server

引言

你还在为 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 配置方案

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
  };
};

数据库方案对比

功能对比

特性MongoDBPostgreSQL
数据模型文档模型关系模型+JSONB
事务支持支持(4.0+)完全支持
索引类型B树、哈希、地理空间等B树、GiST、GIN等
查询能力MongoDB查询语言SQL+JSON函数
扩展性水平扩展垂直+有限水平扩展
全文搜索基本支持高级全文搜索
地理空间查询支持支持(PostGIS)

性能对比

在不同场景下,两种数据库表现各有优势:

  1. 写性能:MongoDB 通常在简单写入场景下表现更好,因其文档模型减少了关联操作。

  2. 读性能

    • 简单查询:两者性能相近
    • 复杂关联查询:PostgreSQL 更优
    • JSON 操作:PostgreSQL 的 JSONB 性能通常优于 MongoDB
  3. 索引性能

    • 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();
});

监控与维护

  1. MongoDB 监控

    • 使用 MongoDB Compass 监控性能
    • 配置慢查询日志
    • 定期运行 db.stats()db.collection.stats()
  2. PostgreSQL 监控

    • 使用 pg_stat_statements 跟踪查询性能
    • 配置 auto_explain 记录慢查询
    • 定期 VACUUM 和 ANALYZE

总结

Parse Server 的数据库抽象层为开发者提供了灵活选择数据库的能力。MongoDB 和 PostgreSQL 各有优势,选择时应根据项目需求、团队熟悉度和长期维护成本综合考虑。

无论选择哪种数据库,都应:

  • 合理配置连接池和缓存
  • 为常用查询创建适当索引
  • 定期监控和优化性能
  • 根据业务增长调整数据库架构

通过本文介绍的配置方法和最佳实践,你可以为 Parse Server 构建高效、可靠的数据存储层,满足不同业务场景的需求。

扩展资源

【免费下载链接】parse-server parse-community/parse-server: Parse Server 是 Parse 后端云服务的开源版本,允许开发者在自己的服务器上托管一个完全功能的Parse服务,以便继续对现有的Parse应用提供支持或者创建新的Parse应用。 【免费下载链接】parse-server 项目地址: https://gitcode.com/gh_mirrors/pa/parse-server

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值