为自己的系统搞个全文搜索

本文围绕Lucene全文检索展开,提到在Java业界其广为人知。介绍了支持中文的ChineseAnalyzer和按时间排序搜索结果的方法,如用IndexOrderSearcher解决排序需求,新版本的MultiFieldQueryParser可同时检索多字段。还给出构建索引的代码,包括从数据库取数据索引等,可定时执行。


在本文我又提到lucene了,在java业界,提到全文检索,几乎没有什么人不知道它。
用google搜索一下,满世界都是有关资料。具有代表性的就是车东的“基于Java的全文索引引擎Lucene简介”,
我要写的也就只有最简单的三板斧,再加上支持中文的ChineseAnalyzer以及按照时间排序的搜索结果排序方法。
这些都可以在其他地方找到相关资料,我只是把他们提出来,作为lucence应用中经常遇到的麻烦解决办法。
去年MSN上面有个朋友跟我提到希望用lucene构建个网站的全文检索,我当时就觉得很简单,直说没问题没问题,
不过他提到一个要求就是搜索结果要安装时间排序,我查阅了些资料,发现lucene并不提供用户自定义排序方式,
而只能按照自己相关性算法排序。后来我在车东的weblucene项目找到了IndexOrderSearcher。
解决了结果排序常规需求。
IndexOrderSearcher跟一般IndexSearch使用差不多,仅仅在构建对象的时候多加一个参数IndexOrderSearcher.ORDER_BY_DOCID_DESC
IndexOrderSearcher indexsearcher = new IndexOrderSearcher("/home/lucenetest/index",IndexOrderSearcher.ORDER_BY_DOCID_DESC);
新版本的lucene还提供了一个MultiFieldQueryParser,可以同时检索多个字段,以前QueryParser比较麻烦。
  private static ChineseAnalyzer chineseAnalyzer = new ChineseAnalyzer();
  public Hits search(String queryText){
        if (queryText == null){
          return null;
 }
 Query query;
 try{
   query = MultiFieldQueryParser.parse(queryText, new String[]{"title"},chineseAnalyzer);
   return indexsearcher.search(query);
 }catch(Exception e){
   return null;
 }
}
下面是构建索引,定时从数据库取出数据索引,做完记录完成时间,我是把时间写入一个txt文件。
package com.test.search;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.cn.*;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.*;
import org.apache.lucene.index.*;

import java.io.*;
import java.sql.*;
import java.util.Date;

import com.test.db.*;
import com.test.utility.*;

/**
 * Title: SearchIndexer
 * Description: 全文索引
 * Copyright:   Copyright (c) 2001
 * Company: test
 * @author Sean
 * @version 1.0
 */
public class SearchIndexer {
  private String indexPath = null;
  protected Analyzer analyzer = new ChineseAnalyzer();

  public SearchIndexer(String s) {
    this.indexPath = s;
  }
  /**
   * 索引某日期以前的所有文档
   * @param fromdate
   * @return
   */
  public final void updateIndex(String fromdate) {
    Connection conn = DbUtil.getCon();
    IndexWriter indexWriter = null;
    try {
      indexWriter = getWriter(false);
     //索引发布系统内部文件
        PreparedStatement pstm = conn.prepareStatement(
            "select title,body,creationtime from document where creationtime > '" + fromdate +
            "' order by creationtime");
        ResultSet rs = pstm.executeQuery();
        while (rs.next()) {
          String creationtime = rs.getString("creationtime");
          String title = rs.getString("title");
          String body = rs.getString("body");

         
          if (title == null || body == null) {
            continue;
          }
          try {
            addDocsToIndex(title,body, creationtime,indexWriter);
          }
          catch (Exception ex) {
            ex.printStackTrace();
          }
       }
      indexWriter.optimize();
    }
    catch (Exception ex) {
      ex.printStackTrace();
    }
    finally {
      try {
        indexWriter.close();
        conn.close();
      }
      catch (Exception e) {
        e.printStackTrace();
      }
    }
  }
  /**
   * 检查索引文件是否存在
   * @param s
   * @return 索引是否存在
   */
  private boolean indexExists(String s) {
    File file = new File(s + File.separator + "segments");
    return file.exists();
  }
  /**
   * 增加一组索引
   * @param title
   * @param body
   * @param creationtime
   * @param indexwriter
   * @return
   */
  private final void addNewsToIndex(String docid, String url,String title, String body,
                                      String ptime, IndexWriter indexwriter) throws
      IOException {
    if (indexwriter == null) {
      return;
    }
    else {
      try {
        Document document = new Document();
        document.add(Field.Text("title", title));
        document.add(Field.Text("body", body));
        document.add(new Field("creationtime", creationtime, true, true, false));
        indexwriter.addDocument(document);
      }
      catch (Exception ex) {
    ex.printStackTrace();
      }
      return;
    }
  }
  /**
   * 取得IndexWriter
   * @param flag 是否新建索引
   * @return IndexWriter
   */
  private IndexWriter getWriter(boolean flag) throws IOException {
    String s = indexPath;
    if (s == null) {
      throw new IOException("索引文件路径设置错误.");
    }
    indexPath = s + File.separator + "search";
    IndexWriter indexwriter = null;
    if (flag) {
      try {
        indexwriter = new IndexWriter(indexPath, analyzer, true);
      }
      catch (Exception exception) {
        System.err.println("ERROR: Failed to create a new index writer.");
        exception.printStackTrace();
      }
    }
    else {
      if (indexExists(indexPath)) {
        try {
          indexwriter = new IndexWriter(indexPath, analyzer, false);
        }
        catch (Exception exception1) {
          System.err.println("ERROR: Failed to open an index writer.");
          exception1.printStackTrace();
        }
      }
      else {
        try {
          indexwriter = new IndexWriter(indexPath, analyzer, true);
        }
        catch (Exception exception2) {
          System.err.println("ERROR: Failed to create a new index writer.");
          exception2.printStackTrace();
        }
      }
    }
    return indexwriter;
  }

  public static void main(String[] args) {
    String lastUpdate = "/home/lucenetest/lastUpdate.txt";
    SearchIndexer searchIndexer = new SearchIndexer("/home/lucenetest/index");
    //取出上次更新时间
    String str = Util.readTxtFile(lastUpdate);
    if(str==null || str.length()==0){
      str = new java.util.Date().toString();
    }
    searchIndexer.updateIndex(str);
    //写入当前时间
    Util.writeTxtFile(lastUpdate,new java.util.Date(),false);
  }
}
写个cmd或者sh在相应操作系统下面定时执行SearchIndexer就可以了。

 

下载lucene包
<think>我们参考引用中提到的在Windows上搭建Ubuntu系统的方法,主要有两种主流方式: 1. 双系统安装(引用[1][2][5]):在硬盘上划分独立分区,分别安装Windows和Ubuntu,通过引导菜单选择启动系统。 2. Windows子系统(引用[4]):使用Windows 10/11内置的WSL(Windows Subsystem for Linux)功能,无需重启即可运行Ubuntu。 根据用户需求,我们分别介绍这两种方法: ### 方法一:双系统安装(传统方式) 适用于需要完整Linux环境、图形界面或开发高性能应用的用户。 **步骤:** 1. **准备安装介质**: - 下载Ubuntu镜像(推荐22.04 LTS版本)[^2]。 - 使用Rufus或UltraISO制作启动U盘(需8GB以上)。 2. **分区**: - 在Windows中打开“磁盘管理”,压缩现有分区(建议至少50GB空闲空间)[^1]。 - 保持空闲空间不分区(供Ubuntu使用)。 3. **BIOS设置**: - 重启电脑,进入BIOS(按键通常为F2、F10、Del等)。 - 禁用“Secure Boot”,启用“Legacy Support”或“UEFI”(根据主板类型选择)。 4. **安装Ubuntu**: - 从U盘启动,选择“Try or Install Ubuntu”。 - 点击“Install Ubuntu”,选择语言、键盘布局。 - 在“安装类型”中选择“其他选项”,手动分区: - 选中空闲空间,点击“+”创建分区: - `交换空间`:大小等于物理内存(8GB内存则填8192MB),类型:swap。 - `/`分区:剩余空间的80%,类型:ext4,挂载点:/。 - `/home`分区:剩余20%,类型:ext4,挂载点:/home。 - 确认引导安装器位置(通常为/dev/sda),点击“现在安装”[^2]。 5. **完成安装**: - 设置用户名密码,等待安装完成。 - 重启后进入GRUB菜单,可选择Windows或Ubuntu。 **注意事项**: - 双系统独立性强,但切换需重启[^1]。 - 如遇引导问题,可使用`Boot-Repair`工具修复。 ### 方法二:WSL(Windows子系统) 适用于轻量级开发、无需图形界面或快速启动Linux环境的用户。 **步骤(以WSL 2为例)**: 1. **启用WSL功能**: - 以管理员身份打开PowerShell,执行: ```powershell dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart ``` - 重启电脑。 2. **安装Linux内核更新包**: - 下载并安装:[WSL 2 Linux内核更新包](https://aka.ms/wsl2kernel)。 3. **设置WSL 2为默认版本**: ```powershell wsl --set-default-version 2 ``` 4. **安装Ubuntu**: - 打开Microsoft Store,搜索“Ubuntu 22.04 LTS”并安装。 - 启动Ubuntu应用,设置用户名密码[^4]。 **WSL优势**: - 无需分区或重启,直接在Windows中运行Linux命令行工具。 - 支持文件互通(Ubuntu目录位于`\\wsl$\Ubuntu-22.04`)。 ### 两种方法对比 | **特性** | **双系统** | **WSL** | |----------------|---------------------|-----------------------| | 性能 | 原生性能,支持GPU | 接近原生(WSL 2) | | 图形界面 | 完整支持 | 需额外配置X服务器 | | 硬盘访问 | 分区隔离 | 直接访问NTFS分区 | | 适用场景 | 游戏开发、3D渲染等 | Web开发、命令行工具等 | 根据您的需求选择合适方案。推荐开发人员首选WSL,嵌入式开发或图形应用选双系统。 §§相关问题§§ 1. 双系统安装后如何修复Windows引导? 2. WSL如何配置图形界面(GUI)? 3. 如何在WSL中访问USB设备? 4. 双系统下如何共享文件? 5. 如何卸载Ubuntu双系统? </think>### Windows系统上搭建Ubuntu系统的方法 在Windows系统上搭建Ubuntu环境主要有三种主流方法,根据您的需求和硬件配置选择: --- #### 方法一:双系统安装(推荐) 适用于需要完整Linux环境、直接硬件访问和高性能的场景(如嵌入式开发、深度学习) **准备工作**: 1. 下载Ubuntu镜像(建议22.04 LTS)[^2] 2. 准备≥8GB的U盘 3. 备份Windows重要数据 4. 确保硬盘有≥30GB未分配空间 **安装步骤**: 1. **制作启动盘**: - 使用Rufus或UltraISO将Ubuntu ISO写入U盘(选择GPT分区方案,UEFI启动)[^2] ```powershell # Rufus命令行示例(需管理员权限) rufus.exe -d ubuntu-22.04-desktop-amd64.iso --partition-scheme=GPT --target-system=UEFI ``` 2. **磁盘分区**: - Win+X → 磁盘管理 → 压缩卷(建议50GB以上) - **保留未分配空间**不格式化[^1] 3. **BIOS设置**: - 重启按F2/Del进入BIOS - 禁用Secure Boot → 启用UEFI模式 → 设置U盘为首选启动项 4. **安装Ubuntu**: - 从U盘启动 → 选择"Install Ubuntu" - 分区时选择**"与Windows共存"**(自动识别未分配空间)[^1] - 关键分区设置: - `/` 根分区:EXT4格式,≥30GB - `swap` 交换分区:内存大小的1-2倍 - EFI分区:共享Windows EFI分区(无需新建) 5. **完成安装**: - 设置用户名密码 → 安装GRUB引导器 - 重启后在GRUB菜单选择OS启动[^5] --- #### 方法二:Windows子系统(WSL 2) 适用于轻量级开发环境(无需重启/图形界面需求低) **安装步骤**: 1. 启用WSL功能(管理员PowerShell): ```powershell dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart ``` 2. 安装[WSL 2内核更新包](https://aka.ms/wsl2kernel) 3. 设置WSL 2为默认版本: ```powershell wsl --set-default-version 2 ``` 4. Microsoft Store安装**Ubuntu 22.04 LTS**[^4] 5. 启动应用完成初始化(设置Linux用户名密码) --- #### 方法三:虚拟机安装 适用于快速测试/临时使用(VirtualBox/VMware) **安装步骤**: 1. 下载[VirtualBox](https://www.virtualbox.org/) 2. 新建虚拟机: - 类型:Linux → 版本:Ubuntu(64-bit) - 内存≥4GB → 硬盘≥30GB(VDI动态分配) 3. 挂载Ubuntu ISO镜像启动安装 4. 安装增强功能支持双向剪贴板/文件共享 --- ### 方案对比 | **特性** | 双系统 | WSL 2 | 虚拟机 | |----------------|--------------------------|---------------------------|----------------------| | 性能 | ⭐⭐⭐⭐⭐ (原生) | ⭐⭐⭐⭐ (接近原生) | ⭐⭐ (有损耗) | | 硬件支持 | 完整GPU/USB访问 | 需配置GPU直通 | 受限 | | 磁盘空间 | 独立分区(安全隔离) | 共享NTFS(可能有权限问题)| 单文件存储 | | 启动速度 | 需重启 | 秒级启动 | 中等 | | 适用场景 | 嵌入式/高性能计算 | Python/Web开发 | 临时测试 | > 💡 **推荐选择**:开发选WSL 2,生产环境选双系统,短期测试用虚拟机
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值