倒排索引简单实现
倒排索引
倒排索引源于实际应用中需要根据属性的值来查找记录。这种索引表中的每一项都包括一个属性值和具有该属性值的各记录的地址。由于不是由记录来确定属性值,而是由属性值来确定记录的位置,因而称为倒排索引(inverted index)。带有倒排索引的文件我们称为倒排索引文件,简称倒排文件(inverted file)。(来源百度)
SQL:
CREATE TABLE `term` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`term` varchar(255) DEFAULT NULL,
`content_ids` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `un_term` (`term`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4;
CREATE TABLE `content` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`content` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4;
JAVA 代码
controller层
@Resource
private ItemAndContentMapper itemAndContentMapper;
/**
* 测试接口 添加
*
* @return 结果
*/
@GetMapping("add")
@Transactional(rollbackFor = Exception.class)
public CommonResult test(String content) {
Content build = Content.builder().content(content).build();
this.itemAndContentMapper.insertContent(build);
List<Item> collect = Arrays.stream(StringUtils.split(content, " ")).map(item ->
Item.builder().term(item).contentIds(String.valueOf(build.getId())).build()).collect(Collectors.toList());
this.itemAndContentMapper.batchItem(collect);
return CommonResult.ok();
}
/**
* 测试接口 查询
*
* @return 结果
*/
@GetMapping("query")
public CommonResult query(String content) {
String s = this.itemAndContentMapper.queryContentIds(content);
if (StringUtils.isBlank(s)) {
return CommonResult.ok();
}
List<Content> contents = this.itemAndContentMapper.queryListContentByIds(s);
return CommonResult.ok(contents);
}
DAO层
package com.qzboot.admin.model.mapper;
import com.qzboot.common.entity.api.Content;
import com.qzboot.common.entity.api.Item;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* @author: zhangqi
* @create: 2021/12/26 13:48
*/
@Mapper
@Repository
public interface ItemAndContentMapper {
/**
* 批量插入 item
*
* @param items 关键字
* @return 条件
*/
@Insert("<script>" +
"insert into term (term,content_ids) value " +
" <foreach collection='items' item='i' separator=','> " +
" (#{i.term},#{i.contentIds}) " +
" </foreach> " +
" ON DUPLICATE KEY UPDATE \n" +
" `content_ids` = concat(VALUES(`content_ids`) , if(`content_ids` is null,'',',') , content_ids ) " +
"</script> ")
int batchItem(@Param("items") List<Item> items);
/**
* 插入正文
*
* @param content 正文内容
* @return 更新条数
*/
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
@Insert("insert into content (content) value (#{content.content}) ")
int insertContent(@Param("content") Content content);
/**
* 查询关键字查询正文ids
*
* @param term 关键字
* @return 正文Ids
*/
@Select("SELECT\n" +
"term.content_ids\n" +
"FROM\n" +
"term\n" +
"WHERE\n" +
"term.term = #{term}\n")
String queryContentIds(@Param("term") String term);
/**
* 查询正文
*
* @param ids ids
* @return 正文
*/
@Select("SELECT\n" +
"content.id,\n" +
"content.content\n" +
"FROM\n" +
"content\n" +
"WHERE\n" +
"content.id in (${ids})\n")
List<Content> queryListContentByIds(@Param("ids") String ids);
}