ES 课程示例文档

在将关系数据库中的数据导入 Elasticsearch 以实现高效搜索的过程中,本文展示了如何使用 Java 集成 PostgreSQL 和 Elasticsearch。通过创建索引、批量导入数据、以及构建复杂查询,我们能够实现对大量课程数据的快速检索和分析。此方法不仅提高了数据查询的效率,还为用户提供了更为灵活的搜索功能,适用于需要处理大规模数据集的应用场景。

表结构和数据

首先,我们创建一个 PostgreSQL 表 rumi_sjsu_class_schedule_2024_fall 来存储 2024 年秋季学期的课程信息。以下是该表的结构定义:

DROP TABLE IF EXISTS "public"."rumi_sjsu_class_schedule_2024_fall";
CREATE TABLE "public"."rumi_sjsu_class_schedule_2024_fall" (
  "id" "pg_catalog"."int8" NOT NULL,
  "term" "pg_catalog"."varchar" COLLATE "pg_catalog"."default",
  "section" "pg_catalog"."varchar" COLLATE "pg_catalog"."default",
  "section_url" "pg_catalog"."varchar" COLLATE "pg_catalog"."default",
  "class_number" "pg_catalog"."varchar" COLLATE "pg_catalog"."default",
  "mode_of_instruction" "pg_catalog"."varchar" COLLATE "pg_catalog"."default",
  "course_title" "pg_catalog"."varchar" COLLATE "pg_catalog"."default",
  "satisfies" "pg_catalog"."varchar" COLLATE "pg_catalog"."default",
  "units" "pg_catalog"."varchar" COLLATE "pg_catalog"."default",
  "type" "pg_catalog"."varchar" COLLATE "pg_catalog"."default",
  "days" "pg_catalog"."varchar" COLLATE "pg_catalog"."default",
  "times" "pg_catalog"."varchar" COLLATE "pg_catalog"."default",
  "instructor" "pg_catalog"."varchar" COLLATE "pg_catalog"."default",
  "instructor_email" "pg_catalog"."varchar" COLLATE "pg_catalog"."default",
  "location" "pg_catalog"."varchar" COLLATE "pg_catalog"."default",
  "dates" "pg_catalog"."varchar" COLLATE "pg_catalog"."default",
  "open_seats" "pg_catalog"."varchar" COLLATE "pg_catalog"."default",
  "notes" "pg_catalog"."text" COLLATE "pg_catalog"."default",
  "source_url" "pg_catalog"."varchar" COLLATE "pg_catalog"."default",
  "remark" "pg_catalog"."varchar" COLLATE "pg_catalog"."default",
  "creator" "pg_catalog"."varchar" COLLATE "pg_catalog"."default" DEFAULT ''::character varying,
  "create_time" "pg_catalog"."timestamp" NOT NULL DEFAULT CURRENT_TIMESTAMP,
  "updater" "pg_catalog"."varchar" COLLATE "pg_catalog"."default" DEFAULT ''::character varying,
  "update_time" "pg_catalog"."timestamp" NOT NULL DEFAULT CURRENT_TIMESTAMP,
  "deleted" "pg_catalog"."int2" NOT NULL DEFAULT 0,
  "tenant_id" "pg_catalog"."int8" NOT NULL DEFAULT 0
);

接下来,向该表中插入 10 条样例数据:

INSERT INTO "public"."rumi_sjsu_class_schedule_2024_fall" VALUES (415453123425030148, 'Fall 2024', 'AAS 1 (Section 07)', 'https://catalog.sjsu.edu/content.php?filter%5B27%5D=AAS&filter%5B29%5D=1&cur_cat_oid=15&navoid=5382', '47613', 'In Person', 'Introduction to Asian American Studies', 'GE: F', '3.0', 'LEC', 'TR', '01:30PM-02:45PM', 'Lawrence Lan', 'mailto:lawrence.lan@sjsu.edu', 'HGH122', '08/21/24-12/09/24', '0', '', 'https://www.sjsu.edu/classes/schedules/fall-2024.php', NULL, '', '2024-08-20 13:23:10.434585', '', '2024-08-20 13:23:10.434585', 0, 0);
INSERT INTO "public"."rumi_sjsu_class_schedule_2024_fall" VALUES (415453123429224456, 'Fall 2024', 'AAS 25 (Section 04)', 'https://catalog.sjsu.edu/content.php?filter%5B27%5D=AAS&filter%5B29%5D=25&cur_cat_oid=15&navoid=5382', '49445', 'Fully Online', 'The Changing Majority: Power and Ethnicity in America', 'GE: F', '3.0', 'LEC', 'TBA', 'TBA', 'Bobby Seals', 'mailto:bobby.m.seals@sjsu.edu', 'ONLINE', '08/21/24-12/09/24', '26', 'FULLY ONLINE - NO designated day/time meetings (TBA). May utilize Canvas. More info at sjsu.edu/ecampus', 'https://www.sjsu.edu/classes/schedules/fall-2024.php', NULL, '', '2024-08-20 13:23:10.434585', '', '2024-08-20 13:23:10.434585', 0, 0);
INSERT INTO "public"."rumi_sjsu_class_schedule_2024_fall" VALUES (415453123433418757, 'Fall 2024', 'AAS 33A (Section 05)', 'https://catalog.sjsu.edu/content.php?filter%5B27%5D=AAS&filter%5B29%5D=33A&cur_cat_oid=15&navoid=5382', '47647', 'In Person', 'Asian Americans in U.S. History I', 'GE: D', '3.0', 'LEC', 'TR', '03:00PM-04:15PM', 'Lawrence Lan', 'mailto:lawrence.lan@sjsu.edu', 'HGH122', '08/21/24-12/09/24', '0', '', 'https://www.sjsu.edu/classes/schedules/fall-2024.php', NULL, '', '2024-08-20 13:23:10.434585', '', '2024-08-20 13:23:10.434585', 0, 0);
INSERT INTO "public"."rumi_sjsu_class_schedule_2024_fall" VALUES (415453123433418763, 'Fall 2024', 'AAS 33B (Section 02)', 'https://catalog.sjsu.edu/content.php?filter%5B27%5D=AAS&filter%5B29%5D=33B&cur_cat_oid=15&navoid=5382', '47661', 'In Person', 'Asian Americans in U.S. History II', 'GE: D+US', '3.0', 'LEC', 'MW', '04:30PM-05:45PM', 'Soo Choi', 'mailto:soo.choi@sjsu.edu', 'DMH358', '08/21/24-12/09/24', '0', 'PV - Prerequisite courses required. See course description.', 'https://www.sjsu.edu/classes/schedules/fall-2024.php', NULL, '', '2024-08-20 13:23:10.434585', '', '2024-08-20 13:23:10.434585', 0, 0);
INSERT INTO "public"."rumi_sjsu_class_schedule_2024_fall" VALUES (415453123437613061, 'Fall 2024', 'AAS 180 (Section 41)', 'https://catalog.sjsu.edu/content.php?filter%5B27%5D=AAS&filter%5B29%5D=180&cur_cat_oid=15&navoid=5382', '41713', 'Fully Online', 'Individual Studies', '', '4.0', 'SUP', 'TBA', 'TBA', 'Staff', '', 'ONLINE', '08/21/24-12/09/24', '3', 'RC - Requires department release of permission number. RD - Requires department approval. RE - Requires negotiated agreements or contracts. Consult department. RO - Not available to Open University students. FULLY ONLINE - NO designated day/time meetings (TBA). May utilize Canvas. More info at sjsu.edu/ecampus', 'https://www.sjsu.edu/classes/schedules/fall-2024.php', NULL, '', '2024-08-20 13:23:10.434585', '', '2024-08-20 13:23:10.434585', 0, 0);
INSERT INTO "public"."rumi_sjsu_class_schedule_2024_fall" VALUES (415453123492139040, 'Fall 2024', 'ATH 12S (Section 01)', 'https://catalog.sjsu.edu/content.php?filter%5B27%5D=ATH&filter%5B29%5D=12S&cur_cat_oid=15&navoid=5382', '40020', 'In Person', 'Skills Development, Football', '', '1.0', 'ACT', 'TBA', 'TBA', 'Staff', '', '', '08/21/24-12/09/24', '0', '', 'https://www.sjsu.edu/classes/schedules/fall-2024.php', NULL, '', '2024-08-20 13:23:10.434585', '', '2024-08-20 13:23:10.434585', 0, 0);
INSERT INTO "public"."rumi_sjsu_class_schedule_2024_fall" VALUES (415453123492139041, 'Fall 2024', 'ATH 12S (Section 02)', 'https://catalog.sjsu.edu/content.php?filter%5B27%5D=ATH&filter%5B29%5D=12S&cur_cat_oid=15&navoid=5382', '40021', 'In Person', 'Skills Development, Football', '', '1.0', 'ACT', 'TBA', 'TBA', 'Staff', '', '', '08/21/24-12/09/24', '0', '', 'https://www.sjsu.edu/classes/schedules/fall-2024.php', NULL, '', '2024-08-20 13:23:10.434585', '', '2024-08-20 13:23:10.434585', 0, 0);
INSERT INTO "public"."rumi_sjsu_class_schedule_2024_fall" VALUES (415453123496333312, 'Fall 2024', 'ATH 12S (Section 03)', 'https://catalog.sjsu.edu/content.php?filter%5B27%5D=ATH&filter%5B29%5D=12S&cur_cat_oid=15&navoid=5382', '40022', 'In Person', 'Skills Development, Football', '', '1.0', 'ACT', 'TBA', 'TBA', 'Staff', '', '', '08/21/24-12/09/24', '0', '', 'https://www.sjsu.edu/classes/schedules/fall-2024.php', NULL, '', '2024-08-20 13:23:10.434585', '', '2024-08-20 13:23:10.434585', 0, 0);
INSERT INTO "public"."rumi_sjsu_class_schedule_2024_fall" VALUES (415453123496333313, 'Fall 2024', 'ATH 12S (Section 04)', 'https://catalog.sjsu.edu/content.php?filter%5B27%5D=ATH&filter%5B29%5D=12S&cur_cat_oid=15&navoid=5382', '40023', 'In Person', 'Skills Development, Football', '', '1.0', 'ACT', 'TBA', 'TBA', 'Staff', '', '', '08/21/24-12/09/24', '15', '', 'https://www.sjsu.edu/classes/schedules/fall-2024.php', NULL, '', '2024-08-20 13:23:10.434585', '', '2024-08-20 13:23:10.434585', 0, 0);
INSERT INTO "public"."rumi_sjsu_class_schedule_2024_fall" VALUES (415453123496333344, 'Fall 2024', 'ATH 44I (Section 01)', 'https://catalog.sjsu.edu/content.php?filter%5B27%5D=ATH&filter%5B29%5D=44I&cur_cat_oid=15&navoid=5382', '40054', 'In Person', 'Women''s Soccer', '', '1.0', 'ACT', 'TBA', 'TBA', 'Staff', '', '', '08/21/24-12/09/24', '22', '', 'https://www.sjsu.edu/classes/schedules/fall-2024.php', NULL, '', '2024-08-20 13:23:10.434585', '', '2024-08-20 13:23:10.434585', 0, 0);

Elasticsearch 索引创建、数据导入和搜索

在此示例中,我们使用 Elasticsearch(ES)来创建索引、导入课程数据并执行搜索操作。为了实现这些功能,我们使用了 Java 编写的 SjsuClassScheduleEsService 服务类。

1. 创建 Elasticsearch 索引

首先,我们需要在 Elasticsearch 中创建一个索引来存储课程数据。索引的名称与数据库表名一致。以下是创建索引的方法: import

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;

import com.litongjava.db.activerecord.Db;
import com.litongjava.db.activerecord.Page;
import com.litongjava.db.activerecord.Record;
import com.litongjava.db.activerecord.SqlPara;
import com.litongjava.es.client.Elastic;
import com.litongjava.tio.utils.hutool.StrUtil;
import com.litongjava.tio.utils.json.FastJson2Utils;
public void createIndex() {
    CreateIndexRequest request = new CreateIndexRequest(indexName);
    request.settings(Settings.builder().put("index.max_result_window", 10000000));
    request.source("{}", XContentType.JSON);

    RestHighLevelClient client = Elastic.getClient();
    try {
        CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
        log.info("Index created: " + createIndexResponse.index());
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

在创建索引时,我们配置了索引的最大结果窗口 (index.max_result_window) 以支持更大规模的数据查询。

2. 导入数据库记录到 Elasticsearch

接下来,我们从数据库中提取所有课程记录,并将其批量导入到 Elasticsearch 中。为了优化导入性能,我们采用分页查询,每次处理 1000 条记录:

public void importRecords() {
    Long count = Db.countTable(indexName);
    long round = count / 1000 + 1;

    for (int i = 0; i < round; i++) {
        String sql = "select * from " + indexName + " order by id";
        SqlPara sqlPara = SqlPara.by(sql);
        int pageNo = i + 1;
        Page<Record> page = Db.paginate(pageNo, 1000, sqlPara);
        List<Record> list = page.getList();

        BulkRequest bulkRequest = new BulkRequest();
        log.info("start:" + pageNo);
        for (Record r : list) {
            IndexRequest source = new IndexRequest(indexName)
                .id(r.getLong("id").toString())
                .source(FastJson2Utils.toJson(r.toMap()), XContentType.JSON);
            bulkRequest.add(source);
        }
        log.info("finish:" + pageNo);

        BulkResponse bulk = Elastic.bulk(bulkRequest, RequestOptions.DEFAULT);
        log.info("bulk:{}", bulk);
    }
}

3. 在 Elasticsearch 中搜索课程数据

我们可以通过关键词搜索 Elasticsearch 中的课程数据。搜索方法接受分页参数和搜索关键字,构建查询条件并执行搜索:

public List<Map<String, Object>> search(int pageNo, int pageSize, String key) {
    SearchRequest searchRequest = new SearchRequest(indexName);
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder().trackTotalHits(true);
    BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

    if (StrUtil.isNotEmpty(key)) {
        boolQuery.must(QueryBuilders.queryStringQuery(key));
    }
    sourceBuilder.query(boolQuery);
    sourceBuilder.from((pageNo - 1) * pageSize);
    sourceBuilder.size(pageSize);
    searchRequest.source(sourceBuilder);

    SearchResponse search = Elastic.search(searchRequest, RequestOptions.DEFAULT);
    SearchHit[] hits = search.getHits().getHits();
    List<Map<String, Object>> list = new ArrayList<>(hits.length);
    for (SearchHit hit : hits) {
        Map<String, Object> sourceAsMap = hit.getSourceAsMap();
        list.add(sourceAsMap);
    }
    return list;
}

这段代码的主要功能是从 Elasticsearch 中搜索数据,并返回符合条件的结果。为了实现这一点,代码使用了 SearchSourceBuilderBoolQueryBuilder 来构建搜索查询,下面是具体的解释:

BoolQueryBuildersourceBuilder 的作用

  1. BoolQueryBuilder 的作用

    • BoolQueryBuilder 是 Elasticsearch 中用于构建布尔查询的工具类。布尔查询允许我们结合多个查询条件(例如 mustshouldmust_not 等),来实现复杂的查询逻辑。
    • 在这段代码中,boolQuery 被用来构建搜索条件。如果 key 参数非空,代码使用 queryStringQuery(key) 来进行模糊查询,并将其添加到 boolQuery 中的 must 子句中。这意味着如果 key 非空,Elasticsearch 将在所有字段中查找包含该关键字的记录。
  2. SearchSourceBuilder 的作用

    • SearchSourceBuilder 是 Elasticsearch 中用来构建查询请求的类。它允许我们指定查询的条件、分页信息、排序规则、返回的字段等。
    • 在代码中,sourceBuilder 被用来定义查询的各个部分。首先,它将前面创建的 boolQuery 设置为查询条件,然后通过 fromsize 方法指定分页信息,即从第几条记录开始 (from) 和返回多少条记录 (size)。
    • sourceBuilder.trackTotalHits(true) 的作用是确保查询返回的结果能够追踪到总的匹配数量,这对于分页查询很重要,因为它可以让我们知道总共有多少条记录符合查询条件。

为什么需要 BoolQueryBuildersourceBuilder

  • 灵活性和可扩展性: 使用 BoolQueryBuilder 可以很容易地构建复杂的查询条件。如果以后需要添加更多的查询条件(例如筛选特定字段),可以轻松地将这些条件添加到 BoolQueryBuilder 中。

  • 分页支持SearchSourceBuilder 提供了分页查询的功能,通过 fromsize 方法,可以轻松控制查询的起始位置和返回的记录数量。这使得大规模数据查询的性能得到了优化。

  • 易于维护: 将查询逻辑与查询构建分离有助于代码的可维护性。BoolQueryBuilder 负责构建复杂的查询条件,而 SearchSourceBuilder 负责管理整个查询请求的配置。这种分离使得代码更易于理解和扩展。

总结来说,BoolQueryBuilder 用于构建复杂的查询条件,而 SearchSourceBuilder 用于组织这些条件并配置查询请求的其他选项(如分页)。这两个类的结合使得 Elasticsearch 的搜索功能强大且灵活,能够满足各种查询需求。

4.删除索引

  public void deleteIndex() {
    RestHighLevelClient client = Elastic.getClient();
    DeleteIndexRequest request = new DeleteIndexRequest(indexName);
    try {
      AcknowledgedResponse deleteIndexResponse = client.indices().delete(request, RequestOptions.DEFAULT);
      if (deleteIndexResponse.isAcknowledged()) {
        log.info("Index {} deleted successfully.", indexName);
      } else {
        log.warn("Index {} deletion not acknowledged.", indexName);
      }
    } catch (IOException e) {
      log.error("Error deleting index {}: {}", indexName, e.getMessage());
      throw new RuntimeException(e);
    }
  }

具体工作流程

  1. 创建 PostgreSQL 表和插入数据:首先,我们创建了一个数据库表并插入课程数据。此表将作为课程信息的存储库。
  2. 创建 Elasticsearch 索引:通过 Java 服务类中的 createIndex() 方法,我们在 Elasticsearch 中创建了一个索引,来存储课程信息。
  3. 导入数据到 Elasticsearch:从数据库中分页提取课程数据,并通过批量请求将其导入 Elasticsearch 索引中。这一步确保了大规模数据的高效导入。
  4. 搜索功能:通过 search() 方法,用户可以在 Elasticsearch 中查询课程信息,支持模糊搜索和分页查询。

通过以上步骤,我们成功地将课程数据导入 Elasticsearch 并实现了基本的搜索功能。

测试

package com.litongjava.open.chat.services;

import java.util.List;
import java.util.Map;

import org.junit.Test;

import com.litongjava.jfinal.aop.Aop;
import com.litongjava.open.chat.config.DbConfig;
import com.litongjava.open.chat.config.ElasticSearchConfig;
import com.litongjava.tio.utils.environment.EnvUtils;
import com.litongjava.tio.utils.json.JsonUtils;

public class SjsuClassScheduleEsServiceTest {

  @Test
  public void test() {
    EnvUtils.load();
    new DbConfig().config();
    new ElasticSearchConfig().config();
    SjsuClassScheduleEsService sjsuClassScheduleEsService = Aop.get(SjsuClassScheduleEsService.class);
    sjsuClassScheduleEsService.createIndex();
    sjsuClassScheduleEsService.importRecords();
    List<Map<String, Object>> lists = sjsuClassScheduleEsService.search(1, 10, "AAS 1");
    System.out.println(JsonUtils.toJson(lists));
  }

  @Test
  public void searchLawrenceLan() {
    // Lawrence Lan
    EnvUtils.load();
    new DbConfig().config();
    new ElasticSearchConfig().config();
    SjsuClassScheduleEsService sjsuClassScheduleEsService = Aop.get(SjsuClassScheduleEsService.class);
    List<Map<String, Object>> lists = sjsuClassScheduleEsService.search(1, 10, "Lawrence Lan");
    System.out.println(JsonUtils.toJson(lists));
  }
}

返回的结果

[
  {
    "class_number": "47607",
    "tenant_id": 0,
    "notes": "",
    "section": "AAS 1 (Section 01)",
    "units": "3.0",
    "type": "LEC",
    "source_url": "https://www.sjsu.edu/classes/schedules/fall-2024.php",
    "updater": "",
    "times": "09:00AM-10:15AM",
    "update_time": "2024-08-20 13:23:10.434585",
    "instructor_email": "mailto:joanne.rondilla@sjsu.edu",
    "satisfies": "GE: F",
    "term": "Fall 2024",
    "id": "415453123420835840",
    "section_url": "https://catalog.sjsu.edu/content.php?filter%5B27%5D=AAS&filter%5B29%5D=1&cur_cat_oid=15&navoid=5382",
    "creator": "",
    "create_time": "2024-08-20 13:23:10.434585",
    "mode_of_instruction": "In Person",
    "course_title": "Introduction to Asian American Studies",
    "dates": "08/21/24-12/09/24",
    "deleted": 0,
    "instructor": "Joanne Rondilla",
    "open_seats": "0",
    "days": "MW",
    "location": "DMH358"
  },
  {
    "class_number": "47608",
    "tenant_id": 0,
    "notes": "",
    "section": "AAS 1 (Section 02)",
    "units": "3.0",
    "type": "LEC",
    "source_url": "https://www.sjsu.edu/classes/schedules/fall-2024.php",
    "updater": "",
    "times": "10:30AM-11:45AM",
    "update_time": "2024-08-20 13:23:10.434585",
    "instructor_email": "mailto:joanne.rondilla@sjsu.edu",
    "satisfies": "GE: F",
    "term": "Fall 2024",
    "id": "415453123420835841",
    "section_url": "https://catalog.sjsu.edu/content.php?filter%5B27%5D=AAS&filter%5B29%5D=1&cur_cat_oid=15&navoid=5382",
    "creator": "",
    "create_time": "2024-08-20 13:23:10.434585",
    "mode_of_instruction": "In Person",
    "course_title": "Introduction to Asian American Studies",
    "dates": "08/21/24-12/09/24",
    "deleted": 0,
    "instructor": "Joanne Rondilla",
    "open_seats": "1",
    "days": "MW",
    "location": "DMH358"
  },
  {
    "class_number": "47609",
    "tenant_id": 0,
    "notes": "",
    "section": "AAS 1 (Section 03)",
    "units": "3.0",
    "type": "LEC",
    "source_url": "https://www.sjsu.edu/classes/schedules/fall-2024.php",
    "updater": "",
    "times": "03:00PM-04:15PM",
    "update_time": "2024-08-20 13:23:10.434585",
    "instructor_email": "mailto:joanne.rondilla@sjsu.edu",
    "satisfies": "GE: F",
    "term": "Fall 2024",
    "id": "415453123425030144",
    "section_url": "https://catalog.sjsu.edu/content.php?filter%5B27%5D=AAS&filter%5B29%5D=1&cur_cat_oid=15&navoid=5382",
    "creator": "",
    "create_time": "2024-08-20 13:23:10.434585",
    "mode_of_instruction": "In Person",
    "course_title": "Introduction to Asian American Studies",
    "dates": "08/21/24-12/09/24",
    "deleted": 0,
    "instructor": "Joanne Rondilla",
    "open_seats": "0",
    "days": "MW",
    "location": "CL234"
  },
  {
    "class_number": "47610",
    "tenant_id": 0,
    "notes": "",
    "section": "AAS 1 (Section 04)",
    "units": "3.0",
    "type": "LEC",
    "source_url": "https://www.sjsu.edu/classes/schedules/fall-2024.php",
    "updater": "",
    "times": "12:00PM-01:15PM",
    "update_time": "2024-08-20 13:23:10.434585",
    "instructor_email": "mailto:saugher.nojan@sjsu.edu",
    "satisfies": "GE: F",
    "term": "Fall 2024",
    "id": "415453123425030145",
    "section_url": "https://catalog.sjsu.edu/content.php?filter%5B27%5D=AAS&filter%5B29%5D=1&cur_cat_oid=15&navoid=5382",
    "creator": "",
    "create_time": "2024-08-20 13:23:10.434585",
    "mode_of_instruction": "In Person",
    "course_title": "Introduction to Asian American Studies",
    "dates": "08/21/24-12/09/24",
    "deleted": 0,
    "instructor": "Saugher Nojan",
    "open_seats": "0",
    "days": "TR",
    "location": "HGH122"
  },
  {
    "class_number": "47611",
    "tenant_id": 0,
    "notes": "",
    "section": "AAS 1 (Section 05)",
    "units": "3.0",
    "type": "LEC",
    "source_url": "https://www.sjsu.edu/classes/schedules/fall-2024.php",
    "updater": "",
    "times": "03:00PM-04:15PM",
    "update_time": "2024-08-20 13:23:10.434585",
    "instructor_email": "mailto:wayne.jopanda@sjsu.edu",
    "satisfies": "GE: F",
    "term": "Fall 2024",
    "id": "415453123425030146",
    "section_url": "https://catalog.sjsu.edu/content.php?filter%5B27%5D=AAS&filter%5B29%5D=1&cur_cat_oid=15&navoid=5382",
    "creator": "",
    "create_time": "2024-08-20 13:23:10.434585",
    "mode_of_instruction": "In Person",
    "course_title": "Introduction to Asian American Studies",
    "dates": "08/21/24-12/09/24",
    "deleted": 0,
    "instructor": "Wayne Jopanda",
    "open_seats": "0",
    "days": "MW",
    "location": "HGH122"
  },
  {
    "class_number": "47612",
    "tenant_id": 0,
    "notes": "",
    "section": "AAS 1 (Section 06)",
    "units": "3.0",
    "type": "LEC",
    "source_url": "https://www.sjsu.edu/classes/schedules/fall-2024.php",
    "updater": "",
    "times": "09:00AM-10:15AM",
    "update_time": "2024-08-20 13:23:10.434585",
    "instructor_email": "mailto:lawrence.lan@sjsu.edu",
    "satisfies": "GE: F",
    "term": "Fall 2024",
    "id": "415453123425030147",
    "section_url": "https://catalog.sjsu.edu/content.php?filter%5B27%5D=AAS&filter%5B29%5D=1&cur_cat_oid=15&navoid=5382",
    "creator": "",
    "create_time": "2024-08-20 13:23:10.434585",
    "mode_of_instruction": "In Person",
    "course_title": "Introduction to Asian American Studies",
    "dates": "08/21/24-12/09/24",
    "deleted": 0,
    "instructor": "Lawrence Lan",
    "open_seats": "0",
    "days": "TR",
    "location": "HGH122"
  },
  {
    "class_number": "47613",
    "tenant_id": 0,
    "notes": "",
    "section": "AAS 1 (Section 07)",
    "units": "3.0",
    "type": "LEC",
    "source_url": "https://www.sjsu.edu/classes/schedules/fall-2024.php",
    "updater": "",
    "times": "01:30PM-02:45PM",
    "update_time": "2024-08-20 13:23:10.434585",
    "instructor_email": "mailto:lawrence.lan@sjsu.edu",
    "satisfies": "GE: F",
    "term": "Fall 2024",
    "id": "415453123425030148",
    "section_url": "https://catalog.sjsu.edu/content.php?filter%5B27%5D=AAS&filter%5B29%5D=1&cur_cat_oid=15&navoid=5382",
    "creator": "",
    "create_time": "2024-08-20 13:23:10.434585",
    "mode_of_instruction": "In Person",
    "course_title": "Introduction to Asian American Studies",
    "dates": "08/21/24-12/09/24",
    "deleted": 0,
    "instructor": "Lawrence Lan",
    "open_seats": "0",
    "days": "TR",
    "location": "HGH122"
  },
  {
    "class_number": "48884",
    "tenant_id": 0,
    "notes": "",
    "section": "AAS 1 (Section 08)",
    "units": "3.0",
    "type": "LEC",
    "source_url": "https://www.sjsu.edu/classes/schedules/fall-2024.php",
    "updater": "",
    "times": "01:30PM-02:45PM",
    "update_time": "2024-08-20 13:23:10.434585",
    "instructor_email": "mailto:trung.p.nguyen@sjsu.edu",
    "satisfies": "GE: F",
    "term": "Fall 2024",
    "id": "415453123425030149",
    "section_url": "https://catalog.sjsu.edu/content.php?filter%5B27%5D=AAS&filter%5B29%5D=1&cur_cat_oid=15&navoid=5382",
    "creator": "",
    "create_time": "2024-08-20 13:23:10.434585",
    "mode_of_instruction": "In Person",
    "course_title": "Introduction to Asian American Studies",
    "dates": "08/21/24-12/09/24",
    "deleted": 0,
    "instructor": "Trung Nguyen",
    "open_seats": "0",
    "days": "TR",
    "location": "CL234"
  },
  {
    "class_number": "48882",
    "tenant_id": 0,
    "notes": "",
    "section": "AAS 1 (Section 09)",
    "units": "3.0",
    "type": "LEC",
    "source_url": "https://www.sjsu.edu/classes/schedules/fall-2024.php",
    "updater": "",
    "times": "03:00PM-04:15PM",
    "update_time": "2024-08-20 13:23:10.434585",
    "instructor_email": "mailto:wayne.jopanda@sjsu.edu",
    "satisfies": "GE: F",
    "term": "Fall 2024",
    "id": "415453123429224448",
    "section_url": "https://catalog.sjsu.edu/content.php?filter%5B27%5D=AAS&filter%5B29%5D=1&cur_cat_oid=15&navoid=5382",
    "creator": "",
    "create_time": "2024-08-20 13:23:10.434585",
    "mode_of_instruction": "In Person",
    "course_title": "Introduction to Asian American Studies",
    "dates": "08/21/24-12/09/24",
    "deleted": 0,
    "instructor": "Wayne Jopanda",
    "open_seats": "0",
    "days": "TR",
    "location": "DMH358"
  },
  {
    "class_number": "48883",
    "tenant_id": 0,
    "notes": "",
    "section": "AAS 1 (Section 10)",
    "units": "3.0",
    "type": "LEC",
    "source_url": "https://www.sjsu.edu/classes/schedules/fall-2024.php",
    "updater": "",
    "times": "04:30PM-05:45PM",
    "update_time": "2024-08-20 13:23:10.434585",
    "instructor_email": "mailto:wayne.jopanda@sjsu.edu",
    "satisfies": "GE: F",
    "term": "Fall 2024",
    "id": "415453123429224449",
    "section_url": "https://catalog.sjsu.edu/content.php?filter%5B27%5D=AAS&filter%5B29%5D=1&cur_cat_oid=15&navoid=5382",
    "creator": "",
    "create_time": "2024-08-20 13:23:10.434585",
    "mode_of_instruction": "In Person",
    "course_title": "Introduction to Asian American Studies",
    "dates": "08/21/24-12/09/24",
    "deleted": 0,
    "instructor": "Wayne Jopanda",
    "open_seats": "0",
    "days": "TR",
    "location": "DMH358"
  }
]
[
  {
    "class_number": "47612",
    "tenant_id": 0,
    "notes": "",
    "section": "AAS 1 (Section 06)",
    "units": "3.0",
    "type": "LEC",
    "source_url": "https://www.sjsu.edu/classes/schedules/fall-2024.php",
    "updater": "",
    "times": "09:00AM-10:15AM",
    "update_time": "2024-08-20 13:23:10.434585",
    "instructor_email": "mailto:lawrence.lan@sjsu.edu",
    "satisfies": "GE: F",
    "term": "Fall 2024",
    "id": "415453123425030147",
    "section_url": "https://catalog.sjsu.edu/content.php?filter%5B27%5D=AAS&filter%5B29%5D=1&cur_cat_oid=15&navoid=5382",
    "creator": "",
    "create_time": "2024-08-20 13:23:10.434585",
    "mode_of_instruction": "In Person",
    "course_title": "Introduction to Asian American Studies",
    "dates": "08/21/24-12/09/24",
    "deleted": 0,
    "instructor": "Lawrence Lan",
    "open_seats": "0",
    "days": "TR",
    "location": "HGH122"
  },
  {
    "class_number": "47613",
    "tenant_id": 0,
    "notes": "",
    "section": "AAS 1 (Section 07)",
    "units": "3.0",
    "type": "LEC",
    "source_url": "https://www.sjsu.edu/classes/schedules/fall-2024.php",
    "updater": "",
    "times": "01:30PM-02:45PM",
    "update_time": "2024-08-20 13:23:10.434585",
    "instructor_email": "mailto:lawrence.lan@sjsu.edu",
    "satisfies": "GE: F",
    "term": "Fall 2024",
    "id": "415453123425030148",
    "section_url": "https://catalog.sjsu.edu/content.php?filter%5B27%5D=AAS&filter%5B29%5D=1&cur_cat_oid=15&navoid=5382",
    "creator": "",
    "create_time": "2024-08-20 13:23:10.434585",
    "mode_of_instruction": "In Person",
    "course_title": "Introduction to Asian American Studies",
    "dates": "08/21/24-12/09/24",
    "deleted": 0,
    "instructor": "Lawrence Lan",
    "open_seats": "0",
    "days": "TR",
    "location": "HGH122"
  },
  {
    "class_number": "49244",
    "tenant_id": 0,
    "notes": "",
    "section": "AAS 1 (Section 11)",
    "units": "3.0",
    "type": "LEC",
    "source_url": "https://www.sjsu.edu/classes/schedules/fall-2024.php",
    "updater": "",
    "times": "06:00PM-08:45PM",
    "update_time": "2024-08-20 13:23:10.434585",
    "instructor_email": "mailto:lawrence.lan@sjsu.edu",
    "satisfies": "GE: F",
    "term": "Fall 2024",
    "id": "415453123429224450",
    "section_url": "https://catalog.sjsu.edu/content.php?filter%5B27%5D=AAS&filter%5B29%5D=1&cur_cat_oid=15&navoid=5382",
    "creator": "",
    "create_time": "2024-08-20 13:23:10.434585",
    "mode_of_instruction": "In Person",
    "course_title": "Introduction to Asian American Studies",
    "dates": "08/21/24-12/09/24",
    "deleted": 0,
    "instructor": "Lawrence Lan",
    "open_seats": "0",
    "days": "W",
    "location": "DMH358"
  },
  {
    "class_number": "47647",
    "tenant_id": 0,
    "notes": "",
    "section": "AAS 33A (Section 05)",
    "units": "3.0",
    "type": "LEC",
    "source_url": "https://www.sjsu.edu/classes/schedules/fall-2024.php",
    "updater": "",
    "times": "03:00PM-04:15PM",
    "update_time": "2024-08-20 13:23:10.434585",
    "instructor_email": "mailto:lawrence.lan@sjsu.edu",
    "satisfies": "GE: D",
    "term": "Fall 2024",
    "id": "415453123433418757",
    "section_url": "https://catalog.sjsu.edu/content.php?filter%5B27%5D=AAS&filter%5B29%5D=33A&cur_cat_oid=15&navoid=5382",
    "creator": "",
    "create_time": "2024-08-20 13:23:10.434585",
    "mode_of_instruction": "In Person",
    "course_title": "Asian Americans in U.S. History I",
    "dates": "08/21/24-12/09/24",
    "deleted": 0,
    "instructor": "Lawrence Lan",
    "open_seats": "0",
    "days": "TR",
    "location": "HGH122"
  },
  {
    "class_number": "47648",
    "tenant_id": 0,
    "notes": "",
    "section": "AAS 33A (Section 06)",
    "units": "3.0",
    "type": "LEC",
    "source_url": "https://www.sjsu.edu/classes/schedules/fall-2024.php",
    "updater": "",
    "times": "04:30PM-05:45PM",
    "update_time": "2024-08-20 13:23:10.434585",
    "instructor_email": "mailto:lawrence.lan@sjsu.edu",
    "satisfies": "GE: D",
    "term": "Fall 2024",
    "id": "415453123433418758",
    "section_url": "https://catalog.sjsu.edu/content.php?filter%5B27%5D=AAS&filter%5B29%5D=33A&cur_cat_oid=15&navoid=5382",
    "creator": "",
    "create_time": "2024-08-20 13:23:10.434585",
    "mode_of_instruction": "In Person",
    "course_title": "Asian Americans in U.S. History I",
    "dates": "08/21/24-12/09/24",
    "deleted": 0,
    "instructor": "Lawrence Lan",
    "open_seats": "0",
    "days": "TR",
    "location": "HGH122"
  },
  {
    "class_number": "42785",
    "tenant_id": 0,
    "notes": "Per CSU, ten seats have been reserved for the Course Match Program. Any unused reserved seats will be released before the semester begins. FULLY ONLINE - NO designated day/time meetings (TBA). May utilize Canvas. More info at sjsu.edu/ecampus",
    "section": "POLS 3 (Section 99)",
    "units": "3.0",
    "type": "LEC",
    "source_url": "https://www.sjsu.edu/classes/schedules/fall-2024.php",
    "updater": "",
    "times": "TBA",
    "update_time": "2024-08-20 13:23:10.434585",
    "instructor_email": "mailto:lawrence.quill@sjsu.edu",
    "satisfies": "GE: C2",
    "term": "Fall 2024",
    "id": "415453123773157396",
    "section_url": "https://catalog.sjsu.edu/content.php?filter%5B27%5D=POLS&filter%5B29%5D=3&cur_cat_oid=15&navoid=5382",
    "creator": "",
    "create_time": "2024-08-20 13:23:10.434585",
    "mode_of_instruction": "Fully Online",
    "course_title": "Introduction to Political Thought",
    "dates": "08/21/24-12/09/24",
    "deleted": 0,
    "instructor": "Lawrence Quill",
    "open_seats": "10",
    "days": "TBA",
    "location": "ONLINE"
  },
  {
    "class_number": "43629",
    "tenant_id": 0,
    "notes": "HYBRID - 2 Meeting Patterns: (1) designated In Person with day/time meetings; and (2) NO designated online day/time meetings (TBA). May utilize Canvas. More info at sjsu.edu/ecampus.",
    "section": "POLS 160A (Section 01)",
    "units": "3.0",
    "type": "LEC",
    "source_url": "https://www.sjsu.edu/classes/schedules/fall-2024.php",
    "updater": "",
    "times": "R 10:30AM-11:45AM TBA TBA",
    "update_time": "2024-08-20 13:23:10.434585",
    "instructor_email": "mailto:lawrence.quill@sjsu.edu",
    "satisfies": "",
    "term": "Fall 2024",
    "id": "415453123773157433",
    "section_url": "https://catalog.sjsu.edu/content.php?filter%5B27%5D=POLS&filter%5B29%5D=160A&cur_cat_oid=15&navoid=5382",
    "creator": "",
    "create_time": "2024-08-20 13:23:10.434585",
    "mode_of_instruction": "Hybrid",
    "course_title": "Classical Political Thought",
    "dates": "08/21/24-12/09/24",
    "deleted": 0,
    "instructor": "Lawrence Quill",
    "open_seats": "10",
    "days": "R TBA",
    "location": "DMH160"
  },
  {
    "class_number": "41946",
    "tenant_id": 0,
    "notes": "PD - Prereq - Senior standing. P1 - Prereq - 100W. HYBRID - 2 Meeting Patterns: (1) designated In Person with day/time meetings; and (2) NO designated online day/time meetings (TBA). May utilize Canvas. More info at sjsu.edu/ecampus.",
    "section": "POLS 190 (Section 01)",
    "units": "4.0",
    "type": "SEM",
    "source_url": "https://www.sjsu.edu/classes/schedules/fall-2024.php",
    "updater": "",
    "times": "R 12:00PM-01:15PM TBA TBA",
    "update_time": "2024-08-20 13:23:10.434585",
    "instructor_email": "mailto:lawrence.quill@sjsu.edu",
    "satisfies": "",
    "term": "Fall 2024",
    "id": "415453123773157441",
    "section_url": "https://catalog.sjsu.edu/content.php?filter%5B27%5D=POLS&filter%5B29%5D=190&cur_cat_oid=15&navoid=5382",
    "creator": "",
    "create_time": "2024-08-20 13:23:10.434585",
    "mode_of_instruction": "Hybrid",
    "course_title": "Senior Seminar",
    "dates": "08/21/24-12/09/24",
    "deleted": 0,
    "instructor": "Lawrence Quill",
    "open_seats": "0",
    "days": "R TBA",
    "location": "DMH149A"
  },
  {
    "class_number": "43472",
    "tenant_id": 0,
    "notes": "PD - Prereq - Senior standing. P1 - Prereq - 100W. RC - Requires department release of permission number. RO - Not available to Open University students.",
    "section": "POLS 190H (Section 01)",
    "units": "1.0",
    "type": "SUP",
    "source_url": "https://www.sjsu.edu/classes/schedules/fall-2024.php",
    "updater": "",
    "times": "TBA",
    "update_time": "2024-08-20 13:23:10.434585",
    "instructor_email": "mailto:lawrence.quill@sjsu.edu",
    "satisfies": "",
    "term": "Fall 2024",
    "id": "415453123773157443",
    "section_url": "https://catalog.sjsu.edu/content.php?filter%5B27%5D=POLS&filter%5B29%5D=190H&cur_cat_oid=15&navoid=5382",
    "creator": "",
    "create_time": "2024-08-20 13:23:10.434585",
    "mode_of_instruction": "In Person",
    "course_title": "Honors Thesis",
    "dates": "08/21/24-12/09/24",
    "deleted": 0,
    "instructor": "Lawrence Quill",
    "open_seats": "5",
    "days": "TBA",
    "location": ""
  },
  {
    "class_number": "41466",
    "tenant_id": 0,
    "notes": "PW - Prerequisites, skills or materials are required. Consult the course description or contact department office. FULLY ONLINE - Designated day/time online meetings. May utilize Canvas. More info at sjsu.edu/ecampus",
    "section": "RTVF 161 (Section 80)",
    "units": "3.0",
    "type": "LEC",
    "source_url": "https://www.sjsu.edu/classes/schedules/fall-2024.php",
    "updater": "",
    "times": "03:00PM-05:45PM",
    "update_time": "2024-08-20 13:23:10.434585",
    "instructor_email": "mailto:lschapiro@nineyardsent.com",
    "satisfies": "",
    "term": "Fall 2024",
    "id": "415453123781546106",
    "section_url": "https://catalog.sjsu.edu/content.php?filter%5B27%5D=RTVF&filter%5B29%5D=161&cur_cat_oid=15&navoid=5382",
    "creator": "",
    "create_time": "2024-08-20 13:23:10.434585",
    "mode_of_instruction": "Fully Online",
    "course_title": "Advanced Screenwriting",
    "dates": "08/21/24-12/09/24",
    "deleted": 0,
    "instructor": "Lawrence Schapiro",
    "open_seats": "8",
    "days": "R",
    "location": "ONLINE"
  }
]