万字长文:从缓存文章聊聊Redis OM是怎么个事儿 · 下

1,163 阅读11分钟

在上一篇文章 万字长文:从缓存文章聊聊Redis OM是怎么个事儿 · 上 中,我们详细介绍了 Redis OM 的基础概念,并展示了如何使用 SchemaRepository 进行缓存操作。今天,我们将深入探讨 Redis OM 的搜索、排序、数据结构以及原生查询等功能,并利用这些知识来封装文章相关的缓存与搜索功能。

5. 搜索与排序

Redis OM 提供了强大的搜索和排序功能,使得我们可以轻松地对数据进行全文搜索和排序操作。

5.1 使用 Redis OM 进行全文搜索

Redis OM 基于 RediSearch 提供全文搜索功能。我们可以使用 search 方法在指定字段中进行全文搜索。

示例代码

假设我们有一个定义好的文章 Schema:

import { Schema, Repository } from 'redis-om';

// 定义文章的 Schema
const articleSchema = new Schema('article', {
  title: { type: 'text' },
  author: { type: 'string' },
  publishDate: { type: 'date' },
  content: { type: 'text' },
  tags: { type: 'string[]' }
});

// 创建文章的 Repository
const articleRepository = new Repository(articleSchema, redis);
await articleRepository.createIndex();

// 创建一些示例文章
const articles = [
  {
    title: 'Redis OM 的强大功能',
    author: '张三',
    publishDate: new Date('2023-01-01'),
    content: 'Redis OM 提供了许多强大的功能,包括全文搜索和排序。',
    tags: ['Redis', '搜索']
  },
  {
    title: '使用 Redis 进行数据存储',
    author: '李四',
    publishDate: new Date('2023-02-15'),
    content: 'Redis 是一个高性能的键值数据库,适用于多种数据存储场景。',
    tags: ['Redis', '数据库']
  },
  {
    title: 'Redis 在实际应用中的案例',
    author: '王五',
    publishDate: new Date('2023-03-10'),
    content: '本文介绍了 Redis 在实际应用中的一些成功案例。',
    tags: ['Redis', '案例']
  }
];

// 将文章存储到 Redis
for (const article of articles) {
  await articleRepository.save(article);
}

console.log('示例文章已存储到 Redis');

我们可以使用 search 方法在 titlecontent 字段中进行全文搜索:

  // 搜索标题和正文
  const searchArticles = async (query: string | number | boolean) => {
    const articles = await articleRepository
      .search()
      .where("title")
      .matches(query)
      .or("content")
      .matches(query)
      .return.all();

    return articles;
  };

  const query = "Redis";
  const articleList = await searchArticles(query);

  articleList.forEach((article) => {
    console.log(`标题: ${article.title}, 作者: ${article.author},正文:${article.content}`);
  });

在这段代码中,我们定义了一个 searchArticles 函数,使用 articleRepository.search 方法在 titlecontent 字段中进行全文搜索,并返回所有匹配的文章。

运行结果

 npm run dev

> redisearch@1.0.0 dev
> ts-node src/index.ts

redis connected
示例文章已存储到 Redis
标题: Understanding Redis OM, 作者: John Doe,正文:Redis OM for Node.js simplifies data modeling...
标题: Understanding Redis OM, 作者: John Doe,正文:Redis OM for Node.js simplifies data modeling...
标题: Understanding Redis OM, 作者: John Doe,正文:Redis OM for Node.js simplifies data modeling...
标题: Understanding Redis OM, 作者: John Doe,正文:Redis OM for Node.js simplifies data modeling...
标题: Understanding Redis OM, 作者: John Doe,正文:Redis OM for Node.js simplifies data modeling...
标题: Understanding Redis OM, 作者: John Doe,正文:Redis OM for Node.js simplifies data modeling...
标题: Understanding Redis OM, 作者: John Doe,正文:Redis OM for Node.js simplifies data modeling...
标题: Understanding Redis OM, 作者: John Doe,正文:Redis OM for Node.js simplifies data modeling...
标题: Understanding Redis OM, 作者: John Doe,正文:Redis OM for Node.js simplifies data modeling...
标题: Understanding Redis OM, 作者: John Doe,正文:Redis OM for Node.js simplifies data modeling...
标题: Understanding Redis OM, 作者: John Doe,正文:Redis OM for Node.js simplifies data modeling...
标题: Understanding Redis OM, 作者: John Doe,正文:Redis OM for Node.js simplifies data modeling...
标题: Understanding Redis OM, 作者: John Doe,正文:Redis OM for Node.js simplifies data modeling...
标题: Understanding Redis OM, 作者: John Doe,正文:Redis OM for Node.js simplifies data modeling...
标题: Understanding Redis OM, 作者: John Doe,正文:Redis OM for Node.js simplifies data modeling...
标题: Understanding Redis OM, 作者: John Doe,正文:Redis OM for Node.js simplifies data modeling...
标题: Understanding Redis OM, 作者: John Doe,正文:Redis OM for Node.js simplifies data modeling...
标题: Understanding Redis OM, 作者: John Doe,正文:Redis OM for Node.js simplifies data modeling...
标题: Understanding Redis OM, 作者: John Doe,正文:Redis OM for Node.js simplifies data modeling...
标题: Understanding Redis OM, 作者: John Doe,正文:Redis OM for Node.js simplifies data modeling...
标题: Understanding Redis OM, 作者: John Doe,正文:Redis OM for Node.js simplifies data modeling...
标题: Redis OM 的强大功能, 作者: 张三,正文:Redis OM 提供了许多强大的功能,包括全文搜索和排序。
标题: 使用 Redis 进行数据存储, 作者: 李四,正文:Redis 是一个高性能的键值数据库,适用于多种数据存储场景。
标题: Redis 在实际应用中的案例, 作者: 王五,正文:本文介绍了 Redis 在实际应用中的一些成功案例。

从结果可以看到,最后几条是我们刚刚缓存的。前面几条都是我们昨天文章中的,接下来我做一下排序

5.2 对搜索结果进行排序

Redis OM 允许我们对搜索结果进行排序。我们可以使用 sortAscendingsortDescending 方法对指定字段进行升序或降序排序。这使得我们能够根据需要对查询结果进行更细致的控制和优化。

示例代码

我们可以对搜索结果按 publishDate 字段进行排序,以下是示例代码:

/**
 * 根据查询条件搜索文章并按发布日期排序
 * @param query - 搜索关键词
 * @returns 排序后的文章列表
 */
const searchAndSortArticles = async (query: string | number | boolean) => {
  // 执行搜索并按发布日期升序排序
  const articles = await articleRepository.search()
    .where('title').matches(query)
    .or('content').matches(query)
    .sortAscending('publishDate')
    .return.all();

  return articles;
};

// 示例查询
const query = "Redis";
const sortedArticles = await searchAndSortArticles(query);

// 输出排序后的文章列表
sortedArticles.forEach(article => {
    console.log(`标题: ${article.title}, 作者: ${article.author},正文:${article.content}`);
});

在这段代码中,我们定义了一个 searchAndSortArticles 函数,该函数接受一个查询参数 query,并使用 Redis OM 的 search 方法进行搜索。搜索条件是标题或内容中包含查询关键词的文章。

接着,我们使用 sortAscending 方法对搜索结果按 publishDate 字段进行升序排序。sortAscending 方法的参数是需要排序的字段名称,这里我们选择 publishDate,表示我们希望按照文章的发布日期从早到晚进行排序。

最后,我们使用 return.all() 方法返回所有匹配的文章,并将这些文章按排序后的顺序输出。

完整示例

import { createClient } from "redis";
import { EntityId, Repository, Schema } from "redis-om";

const redis = createClient({ url: "redis://localhost:6380" });
redis.on("error", (err) => console.log("Redis Client Error", err));

/**
 * 定义文章的 Schema
 */
const articleSchema = new Schema("article", {
  title: { type: "text" },
  author: { type: "string" },
  publishDate: { type: "date", sortable: true }, // 将 publishDate 标记为可排序
  content: { type: "text" },
  tags: { type: "string[]" },
});

/**
 * 创建文章的 Repository
 */
const articleRepository = new Repository(articleSchema, redis);

/**
 * 根据查询条件搜索文章的标题和正文
 * @param query - 搜索关键词
 * @returns 匹配的文章列表
 */
const searchArticles = async (query: string | number | boolean) => {
  const articles = await articleRepository
    .search()
    .where("title")
    .matches(query)
    .or("content")
    .matches(query)
    .return.all();

  return articles;
};

/**
 * 根据查询条件搜索文章并按发布日期排序
 * @param query - 搜索关键词
 * @returns 排序后的文章列表
 */
const searchAndSortArticles = async (query: string | number | boolean) => {
  const articles = await articleRepository
    .search()
    .where("title")
    .matches(query)
    .or("content")
    .matches(query)
    .sortAscending("publishDate")
    .return.all();

  return articles;
};

/**
 * 清空所有文章数据
 */
const clearAllArticles = async () => {
  const allArticles = await articleRepository.search().return.all();
  const allIds = allArticles.map(article => article[EntityId as any]);
  await articleRepository.remove(allIds);
};

/**
 * 初始化 Redis 连接和存储示例文章
 */
const initialize = async () => {
  await redis.connect();
  console.log("redis connected");

  await articleRepository.dropIndex(); // 删除现有索引
  await articleRepository.createIndex(); // 重新创建索引

  // 清空现有的数据
  await clearAllArticles();

  // 创建一些示例文章
  const articles = [
    {
      title: "Redis OM 的强大功能",
      author: "张三",
      publishDate: new Date("2023-01-01"),
      content: "Redis OM 提供了许多强大的功能,包括全文搜索和排序。",
      tags: ["Redis", "搜索"],
    },
    {
      title: "使用 Redis 进行数据存储",
      author: "李四",
      publishDate: new Date("2023-02-15"),
      content: "Redis 是一个高性能的键值数据库,适用于多种数据存储场景。",
      tags: ["Redis", "数据库"],
    },
    {
      title: "Redis 在实际应用中的案例",
      author: "王五",
      publishDate: new Date("2023-03-10"),
      content: "本文介绍了 Redis 在实际应用中的一些成功案例。",
      tags: ["Redis", "案例"],
    },
  ];

  // 将文章存储到 Redis
  for (const article of articles) {
    await articleRepository.save(article);
  }

  console.log("示例文章已存储到 Redis");

  const query = "Redis";
  const articleList = await searchArticles(query);

  console.log("搜索结果:");
  articleList.forEach((article) => {
    console.log(`标题: ${article.title}, 作者: ${article.author},正文:${article.content}`);
  });

  const sortedArticles = await searchAndSortArticles(query);

  console.log("排序后的搜索结果:");
  sortedArticles.forEach((article) => {
    console.log(`标题: ${article.title}, 作者: ${article.author},正文:${article.content}`);
  });
};

// 调用初始化函数
initialize().catch((err) => console.error("Error initializing Redis:", err));

通过 Redis OM 的搜索和排序功能,我们可以轻松地对数据进行复杂的查询操作,并按需对结果进行排序。这使得 Redis OM 成为处理大规模数据和实现高效搜索的强大工具。无论是需要按时间排序的新闻文章、按价格排序的商品列表,还是按评分排序的用户评论,Redis OM 都能提供灵活且高效的解决方案。

6. 高级功能

Redis OM 提供了许多高级功能,使得数据存储和查询更加灵活和高效。本节将探讨使用 JSON 和 Hashes 存储数据的优缺点,Redis OM 支持的高级搜索功能,以及如何使用链式查询和原生查询进行复杂查询。

6.1 使用 JSON 和 Hashes 存储数据

Redis OM 支持将数据存储为 JSON 文档或 Hashes。每种存储方式都有其优缺点。

优缺点

  • JSON 存储

    • 优点:
      • 支持嵌套数据结构。
      • 可以使用 JSONPath 进行复杂查询。
      • 更适合存储结构化和半结构化数据。
    • 缺点:
      • 存储和查询开销较大,适合需要复杂查询的场景。
  • Hashes 存储

    • 优点:
      • 存储和查询开销较小。
      • 更适合平面数据结构。
    • 缺点:
      • 不支持嵌套数据结构。
      • 查询功能相对简单。

示例代码

  • JSON 存储
const jsonArticleSchema = new Schema('article', {
  title: { type: 'string' },
  author: { type: 'string' },
  publishDate: { type: 'date', sortable: true  },
  content: { type: 'string' },
  tags: { type: 'string[]' }
}, {
  dataStructure: 'JSON'
});

const jsonArticleRepository = new Repository(jsonArticleSchema, redis);
await jsonArticleRepository.createIndex();
  • Hashes 存储
const hashArticleSchema = new Schema('article', {
  title: { type: 'string' },
  author: { type: 'string' },
  publishDate: { type: 'date', sortable: true  },
  content: { type: 'string' },
  tags: { type: 'string[]' }
}, {
  dataStructure: 'HASH'
});

const hashArticleRepository = new Repository(hashArticleSchema, redis);
await hashArticleRepository.createIndex();

Schema的类型注解SchemaOptions中有如下注释:

    /** The data structure used to store the {@link Entity} in Redis. Can be set
     * to either `JSON` or `HASH`. Defaults to JSON.
     */

如果不显式指定 dataStructure,则 Redis OM 将默认使用 JSON 数据结构来存储实体。

6.2 高级搜索功能(日期搜索、数组搜索等)

Redis OM 支持多种高级搜索功能,包括日期搜索、数组搜索等。

示例代码

  • 日期搜索
const searchByDate = async (date: Date) => {
  const articles = await jsonArticleRepository.search()
    .where('publishDate').on(date)
    .return.all();

  return articles;
};

const date = new Date('2023-01-01');
const articlesByDate = await searchByDate(date);

articlesByDate.forEach(article => {
  console.log(`Title: ${article.title}, Publish Date: ${article.publishDate}`);
});
  • 数组搜索
const searchByTag = async (tag: string) => {
  const articles = await jsonArticleRepository.search()
    .where('tags').contain(tag)
    .return.all();

  return articles;
};

const tag = 'redis';
const articlesByTag = await searchByTag(tag);

articlesByTag.forEach(article => {
  console.log(`Title: ${article.title}, Tags: ${article.tags}`);
});

6.3 链式查询

链式查询使得我们可以组合多个查询条件。

const searchWithChaining = async () => {
  const articles = await jsonArticleRepository.search()
    .where('author').equals('张三')
    .and('tags').contain('redis')
    .or('publishDate').after(new Date('2022-01-01'))
    .return.all();

  return articles;
};

const chainedArticles = await searchWithChaining();

chainedArticles.forEach(article => {
  console.log(`Title: ${article.title}, Author: ${article.author}`);
});

6.4 原生查询

原生查询允许我们使用 RediSearch 的原生查询语法进行复杂查询。

const searchWithRawQuery = async (query: string) => {
  const articles = await jsonArticleRepository.searchRaw(query).return.all();
  return articles;
};

const rawQuery = "@author:{张三} @tags:{redis} @publishDate:[2022 +inf]";
// const rawQuer1 = "@artist:{Mushroomhead} @title:beautiful @year:[1990 +inf]"
const rawQueryArticles = await searchWithRawQuery(rawQuery);

rawQueryArticles.forEach(article => {
  console.log(`Title: ${article.title}, Author: ${article.author}`);
});

通过 Redis OM 的高级功能,我们可以灵活地存储和查询数据,满足各种复杂的业务需求。

完整示例

import { createClient } from "redis";
import { EntityId, Repository, Schema } from "redis-om";

const redis = createClient({ url: "redis://localhost:6380" });
redis.on("error", (err) => console.log("Redis Client Error", err));

/**
 * 定义文章的 Schema
 */
const articleSchema = new Schema("article", {
  title: { type: "text" },
  author: { type: "string" },
  publishDate: { type: "date", sortable: true }, // 将 publishDate 标记为可排序
  content: { type: "text" },
  tags: { type: "string[]" },
}, {
  dataStructure: 'JSON'
});

/**
 * 创建文章的 Repository
 */
const articleRepository = new Repository(articleSchema, redis);

/**
 * 根据查询条件搜索文章的标题和正文
 * @param query - 搜索关键词
 * @returns 匹配的文章列表
 */
const searchArticles = async (query: string | number | boolean) => {
  const articles = await articleRepository
    .search()
    .where("title")
    .matches(query)
    .or("content")
    .matches(query)
    .return.all();

  return articles;
};

/**
 * 根据查询条件搜索文章并按发布日期排序
 * @param query - 搜索关键词
 * @returns 排序后的文章列表
 */
const searchAndSortArticles = async (query: string | number | boolean) => {
  const articles = await articleRepository
    .search()
    .where("title")
    .matches(query)
    .or("content")
    .matches(query)
    .sortAscending("publishDate")
    .return.all();

  return articles;
};

/**
 * 日期搜索
 * @param date - 搜索日期
 * @returns 匹配的文章列表
 */
const searchByDate = async (date: Date) => {
  const articles = await articleRepository.search()
    .where('publishDate').on(date)
    .return.all();

  return articles;
};

/**
 * 数组搜索
 * @param tag - 搜索标签
 * @returns 匹配的文章列表
 */
const searchByTag = async (tag: string) => {
  const articles = await articleRepository.search()
    .where('tags').contain(tag)
    .return.all();

  return articles;
};

/**
 * 链式查询
 * @returns 匹配的文章列表
 */
const searchWithChaining = async () => {
  const articles = await articleRepository.search()
    .where('author').equals('John Doe')
    .and('tags').contain('redis')
    .or('publishDate').after(new Date('2022-01-01'))
    .return.all();

  return articles;
};

/**
 * 原生查询
 * @param query - 原生查询语句
 * @returns 匹配的文章列表
 */
const searchWithRawQuery = async (query: string) => {
  const articles = await articleRepository.searchRaw(query).return.all();
  return articles;
};

/**
 * 清空所有文章数据
 */
const clearAllArticles = async () => {
  const allArticles = await articleRepository.search().return.all();
  const allIds = allArticles.map(article => article[EntityId as any]);
  await articleRepository.remove(allIds);
};

/**
 * 初始化 Redis 连接和存储示例文章
 */
const initialize = async () => {
  await redis.connect();
  console.log("redis connected");

  await articleRepository.dropIndex(); // 删除现有索引
  await articleRepository.createIndex(); // 重新创建索引

  // 清空现有的数据
  await clearAllArticles();

  // 创建一些示例文章
  const articles = [
    {
      title: "Redis OM 的强大功能",
      author: "张三",
      publishDate: new Date("2023-01-01"),
      content: "Redis OM 提供了许多强大的功能,包括全文搜索和排序。",
      tags: ["Redis", "搜索"],
    },
    {
      title: "使用 Redis 进行数据存储",
      author: "李四",
      publishDate: new Date("2023-02-15"),
      content: "Redis 是一个高性能的键值数据库,适用于多种数据存储场景。",
      tags: ["Redis", "数据库"],
    },
    {
      title: "Redis 在实际应用中的案例",
      author: "王五",
      publishDate: new Date("2023-03-10"),
      content: "本文介绍了 Redis 在实际应用中的一些成功案例。",
      tags: ["Redis", "案例"],
    },
  ];

  // 将文章存储到 Redis
  for (const article of articles) {
    await articleRepository.save(article);
  }

  console.log("示例文章已存储到 Redis");

  const query = "Redis";
  const articleList = await searchArticles(query);

  console.log("搜索结果:");
  articleList.forEach((article) => {
    console.log(`标题: ${article.title}, 作者: ${article.author},正文:${article.content}`);
  });

  const sortedArticles = await searchAndSortArticles(query);

  console.log("排序后的搜索结果:");
  sortedArticles.forEach((article) => {
    console.log(`标题: ${article.title}, 作者: ${article.author},正文:${article.content}`);
  });

  const date = new Date('2023-01-01');
  const articlesByDate = await searchByDate(date);

  console.log("按日期搜索结果:");
  articlesByDate.forEach(article => {
    console.log(`标题: ${article.title}, 发布日期: ${article.publishDate}`);
  });

  const tag = 'Redis';
  const articlesByTag = await searchByTag(tag);

  console.log("按标签搜索结果:");
  articlesByTag.forEach(article => {
    console.log(`标题: ${article.title}, 标签: ${article.tags}`);
  });

  const chainedArticles = await searchWithChaining();

  console.log("链式查询结果:");
  chainedArticles.forEach(article => {
    console.log(`标题: ${article.title}, 作者: ${article.author}`);
  });

  // 原生查询语法
  const rawQuery = "@author:{张三} @tags:{redis} @publishDate:[2022 +inf]";
  // const rawQuer1 = "@artist:{Mushroomhead} @title:beautiful @year:[1990 +inf]"
  const rawQueryArticles = await searchWithRawQuery(rawQuery);

  console.log("原生查询结果:");
  rawQueryArticles.forEach(article => {
    console.log(`标题: ${article.title}, 作者: ${article.author}`);
  });
};

// 调用初始化函数
initialize().catch((err) => console.error("Error initializing Redis:", err));

总结

Redis OM 提供了强大的搜索和排序功能,基于 RediSearch 实现全文搜索,用户可以使用 search 方法在指定字段中进行全文搜索,并通过 sortAscendingsortDescending 方法对搜索结果进行排序。此外,Redis OM 支持使用 JSON 和 Hashes 存储数据,JSON 存储适合复杂嵌套结构,支持复杂查询;Hashes 存储适合平面结构,查询性能较高。高级搜索功能包括日期搜索、数组搜索、链式查询和原生查询,使得数据查询更加灵活和高效。总体来说,Redis OM 提供了全面的搜索和排序功能,支持多种数据存储方式和高级查询功能,使得数据存储和查询变得更加灵活和高效,能够满足各种复杂的业务需求。

附件——完整封装

import { createClient } from "redis";
import { EntityId, Repository, Schema, Search } from "redis-om";

const redis = createClient({ url: "redis://localhost:6380" });
redis.on("error", (err) => console.log("Redis Client Error", err));

/**
 * 定义文章的 Schema
 */
const articleSchema = new Schema(
  "article",
  {
    title: { type: "text" },
    author: { type: "string" },
    publishDate: { type: "date", sortable: true },
    content: { type: "text" },
    tags: { type: "string[]" },
  },
  {
    dataStructure: "JSON",
  }
);

/**
 * 创建文章的 Repository
 */
const articleRepository = new Repository(articleSchema, redis);

/**
 * 搜索文章
 * @param field - 搜索字段
 * @param query - 搜索关键词
 * @param sortField - 排序字段(可选)
 * @param sortOrder - 排序顺序(asc 或 desc,可选)
 * @returns 匹配的文章列表
 */
const searchArticles = async (
  field: string,
  query: string | number | boolean,
  sortField?: string,
  sortOrder: "asc" | "desc" = "asc"
) => {
  if (sortField) {
    if (sortOrder === "asc") {
      return articleRepository
        .search()
        .where(field)
        .matches(query)
        .sortAscending(sortField)
        .return.all();
    } else {
      return await articleRepository
        .search()
        .where(field)
        .matches(query)
        .sortDescending(sortField)
        .return.all();
    }
  }

  return await articleRepository
    .search()
    .where(field)
    .matches(query)
    .return.all();
};

/**
 * 日期搜索
 * @param date - 搜索日期
 * @returns 匹配的文章列表
 */
const searchByDate = async (date: Date) => {
  return await articleRepository
    .search()
    .where("publishDate")
    .on(date)
    .return.all();
};

/**
 * 数组搜索
 * @param tag - 搜索标签
 * @returns 匹配的文章列表
 */
const searchByTag = async (tag: string) => {
  return await articleRepository
    .search()
    .where("tags")
    .contain(tag)
    .return.all();
};

/**
 * 链式查询
 * @param conditions - 查询条件数组
 * @returns 匹配的文章列表
 */
const searchWithChaining = async (
  conditions: { field: string; operator: string; value: any }[]
) => {
  let search: Search<Record<string, any>> = articleRepository.search();

  conditions.forEach((condition) => {
    const { field, operator, value } = condition;
    switch (operator) {
      case "equals":
        search = search.where(field).equals(value);
        break;
      case "contain":
        search = search.where(field).contain(value);
        break;
      case "after":
        search = search.where(field).after(value);
        break;
      case "before":
        search = search.where(field).before(value);
        break;
      case "on":
        search = search.where(field).on(value);
        break;
      default:
        throw new Error(`Unsupported operator: ${operator}`);
    }
  });

  return await search.return.all();
};

/**
 * 原生查询
 * @param query - 原生查询语句
 * @returns 匹配的文章列表
 */
const searchWithRawQuery = async (query: string) => {
  return await articleRepository.searchRaw(query).return.all();
};

/**
 * 清空所有文章数据
 */
const clearAllArticles = async () => {
  const allArticles = await articleRepository.search().return.all();
  const allIds = allArticles.map((article) => article[EntityId as any]);
  await articleRepository.remove(allIds);
};

/**
 * 初始化 Redis 连接和存储示例文章
 */
const initialize = async () => {
  await redis.connect();
  console.log("redis connected");

  await articleRepository.dropIndex();
  await articleRepository.createIndex();

  await clearAllArticles();

  const articles = [
    {
      title: "Redis OM 的强大功能",
      author: "张三",
      publishDate: new Date("2023-01-01"),
      content: "Redis OM 提供了许多强大的功能,包括全文搜索和排序。",
      tags: ["Redis", "搜索"],
    },
    {
      title: "使用 Redis 进行数据存储",
      author: "李四",
      publishDate: new Date("2023-02-15"),
      content: "Redis 是一个高性能的键值数据库,适用于多种数据存储场景。",
      tags: ["Redis", "数据库"],
    },
    {
      title: "Redis 在实际应用中的案例",
      author: "王五",
      publishDate: new Date("2023-03-10"),
      content: "本文介绍了 Redis 在实际应用中的一些成功案例。",
      tags: ["Redis", "案例"],
    },
  ];

  for (const article of articles) {
    await articleRepository.save(article);
  }