Compare commits

...

2 Commits

Author SHA1 Message Date
  liuhuazhong a00c04d757 test 1 year ago
  liuhuazhong 2a40f169d3 kg部分代码 1 year ago
15 changed files with 572 additions and 0 deletions
Split View
  1. +15
    -0
      ruoyi-modules/management-platform/pom.xml
  2. +15
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/config/Neo4jConfig.java
  3. +124
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/kg/MatKGController.java
  4. +15
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/material/DOI.java
  5. +29
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/material/MaterialEntity.java
  6. +15
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/material/NERTag.java
  7. +16
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/material/PartOfText.java
  8. +14
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/material/PreferredEntity.java
  9. +8
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/repository/MatKGRepository.java
  10. +32
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/MatKGServiceImpl.java
  11. +154
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/Neo4JDBService.java
  12. +34
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/ExcelReader.java
  13. +35
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/ExcelReaderInputStream.java
  14. +14
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/MatKGVo.java
  15. +52
    -0
      ruoyi-modules/management-platform/src/test/java/com/ruoyi/platform/utils/ExcelReaderTest.java

+ 15
- 0
ruoyi-modules/management-platform/pom.xml View File

@@ -248,6 +248,21 @@
<artifactId>hutool-all</artifactId>
<version>5.8.5</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>4.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>


+ 15
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/config/Neo4jConfig.java View File

@@ -0,0 +1,15 @@
package com.ruoyi.platform.config;

import org.neo4j.cypherdsl.core.renderer.Dialect;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class Neo4jConfig {
@Bean
org.neo4j.cypherdsl.core.renderer.Configuration cypherDslConfiguration() {
return org.neo4j.cypherdsl.core.renderer.Configuration.newConfig()
.withDialect(Dialect.NEO4J_5).build();
}
}

+ 124
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/kg/MatKGController.java View File

@@ -0,0 +1,124 @@
package com.ruoyi.platform.controller.kg;

import com.ruoyi.common.core.domain.R;
import com.ruoyi.platform.utils.ExcelReaderInputStream;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Map;

@RestController
@RequestMapping("/kg")
public class MatKGController {

@PostMapping("/uploadOntology")
public R<String> uploadOntology(@RequestParam("file") MultipartFile file,
@RequestParam("param") String param) {
if (file.isEmpty()) {
return R.fail("文件为空");
}

try {
// 直接读取文件内容为字符串
String jsonContent = new String(file.getBytes(), StandardCharsets.UTF_8);

return R.ok();
} catch (Exception e) {
return R.fail("文件处理失败: " + e.getMessage());
}
}

@PostMapping("/uploadKGData")
public R<String> uploadKGData(@RequestParam("file") MultipartFile file,
@RequestParam("id") String id) {
if (file.isEmpty()) {
return R.fail("文件为空");
}
// 检查文件类型
String contentType = file.getContentType();
String fileName = file.getOriginalFilename();
if (!isValidFileType(contentType, fileName)) {
return R.fail("不支持的文件格式。请上传CSV、XLSX或JSON文件。");
}

try {
// 创建目标文件
InputStream inputStream = file.getInputStream();

// 处理文件和参数
processJsonFile(inputStream, id);

return R.ok();
} catch (Exception e) {
return R.fail("文件处理失败: " + e.getMessage());
}
}

private void processJsonFile(InputStream inputStream, String id) {
ExcelReaderInputStream<Map> reader = new ExcelReaderInputStream<>(inputStream,Map.class,data->{
//todo some logic
});

// 读取Excel文件
reader.read();
}

@PostMapping("/uploadKGData2")
public R<String> uploadKGData2(@RequestParam("file") MultipartFile file,
@RequestParam("param") String param) {
if (file.isEmpty()) {
return R.fail("文件为空");
}
// 检查文件类型
String contentType = file.getContentType();
String fileName = file.getOriginalFilename();
if (!isValidFileType(contentType, fileName)) {
return R.fail("不支持的文件格式。请上传CSV、XLSX或JSON文件。");
}

try {
// 创建目标文件
File targetFile = new File("uploadDir", file.getOriginalFilename());
// 确保目录存在
if (!targetFile.getParentFile().exists()) {
targetFile.getParentFile().mkdirs();
}
// 将文件写入目标路径
file.transferTo(targetFile);

// 处理文件和参数
// processJsonFile(targetFile, param);

return R.ok("文件上传并处理成功,参数: " + param);
} catch (Exception e) {
return R.fail("文件处理失败: " + e.getMessage());
}
}

private boolean isValidFileType(String contentType, String fileName) {
// 检查文件扩展名
String extension = getFileExtension(fileName);

// 检查MIME类型
if ("application/json".equals(contentType) || "text/csv".equals(contentType) || "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet".equals(contentType)) {
return true;
}

// 检查文件扩展名
return "csv".equalsIgnoreCase(extension) || "xlsx".equalsIgnoreCase(extension) || "json".equalsIgnoreCase(extension);
}

private String getFileExtension(String fileName) {
if (fileName != null && fileName.contains(".")) {
return fileName.substring(fileName.lastIndexOf('.') + 1);
}
return "";
}

}

+ 15
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/material/DOI.java View File

@@ -0,0 +1,15 @@
package com.ruoyi.platform.domain.material;

import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.neo4j.core.schema.Node;

@Node
@Data
@AllArgsConstructor
public class DOI {
@Id
private String doi; // DOI
private Integer year;// YEAR
}

+ 29
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/material/MaterialEntity.java View File

@@ -0,0 +1,29 @@
package com.ruoyi.platform.domain.material;

import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.neo4j.core.schema.Node;
import org.springframework.data.neo4j.core.schema.Relationship;

@Data
@Node
public class MaterialEntity {
@Id
private String id;

private String entity;

@Relationship(type = "HAS_ENTITY")
private PartOfText partOfText;

@Relationship(type = "HAS_NER_TAG")

private NERTag nerTag;

@Relationship(type = "HAS_DOI")
private DOI doi;

@Relationship(type = "HAS_PREFERRED_ENTITY")
private PreferredEntity preferredEntity;
}


+ 15
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/material/NERTag.java View File

@@ -0,0 +1,15 @@
package com.ruoyi.platform.domain.material;

import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.neo4j.core.schema.Node;

@Node
@Data
@AllArgsConstructor
public class NERTag {
@Id
private String tag; // NER_Tag

}

+ 16
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/material/PartOfText.java View File

@@ -0,0 +1,16 @@
package com.ruoyi.platform.domain.material;

import cn.hutool.core.util.IdUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.neo4j.core.schema.Node;

@Node
@Data
@AllArgsConstructor
public class PartOfText {
@Id
private String text; // Part_of_text

}

+ 14
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/material/PreferredEntity.java View File

@@ -0,0 +1,14 @@
package com.ruoyi.platform.domain.material;

import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.neo4j.core.schema.Node;

@Node
@Data
@AllArgsConstructor
public class PreferredEntity {
@Id
private String preferredEntity;
}

+ 8
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/repository/MatKGRepository.java View File

@@ -0,0 +1,8 @@
package com.ruoyi.platform.repository;

import com.ruoyi.platform.domain.material.MaterialEntity;
import org.springframework.data.neo4j.repository.Neo4jRepository;

public interface MatKGRepository
extends Neo4jRepository<MaterialEntity, String> {
}

+ 32
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/MatKGServiceImpl.java View File

@@ -0,0 +1,32 @@
package com.ruoyi.platform.service.impl;

import com.ruoyi.platform.domain.material.MaterialEntity;
import com.ruoyi.platform.repository.MatKGRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class MatKGServiceImpl {

@Autowired
private MatKGRepository repository;

public MaterialEntity save(MaterialEntity entity) {
return repository.save(entity);
}

public List<MaterialEntity> saveAll(List<MaterialEntity> entity) {
return repository.saveAll(entity);
}

public Optional<MaterialEntity> findById(String id) {
return repository.findById(id);
}

public void deleteById(String id) {
repository.deleteById(id);
}
}

+ 154
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/Neo4JDBService.java View File

@@ -0,0 +1,154 @@
package com.ruoyi.platform.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.neo4j.core.Neo4jClient;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.Random;

@Service
public class Neo4JDBService {

@Autowired
private Neo4jClient neo4jClient;

private static final String CHARACTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
private static final Random RANDOM = new Random();
private static final int NAME_LENGTH = 10; // 数据库名称的长度

public void createDatabase(String dbName) {
neo4jClient.query("CREATE DATABASE $dbName")
.bind(dbName).to("dbName")
.run();
}

public void dropDatabase(String dbName) {
neo4jClient.query("DROP DATABASE $dbName")
.bind(dbName).to("dbName")
.run();
}

public void createNode(String nodeType, Map<String, Object> properties) {
StringBuilder query = new StringBuilder("CREATE (n:" + nodeType + " {");
properties.forEach((key, value) -> query.append(key).append(": $").append(key).append(", "));
query.setLength(query.length() - 2); // 移除最后的逗号和空格
query.append("})");

Neo4jClient.UnboundRunnableSpec neo4jQuery = neo4jClient.query(query.toString());
properties.forEach((key, value) -> neo4jQuery.bind(value).to(key));
neo4jQuery.run();
}

public void updateNode(String nodeType, String identifierKey, Object identifierValue, Map<String, Object> properties) {
StringBuilder query = new StringBuilder("MATCH (n:" + nodeType + " {" + identifierKey + ": $" + identifierKey + "}) SET ");
properties.forEach((key, value) -> query.append("n.").append(key).append(" = $").append(key).append(", "));
query.setLength(query.length() - 2); // 移除最后的逗号和空格

Neo4jClient.UnboundRunnableSpec neo4jQuery = neo4jClient.query(query.toString());
neo4jQuery.bind(identifierValue).to(identifierKey);
properties.forEach((key, value) -> neo4jQuery.bind(value).to(key));
neo4jQuery.run();
}

public void deleteNode(String nodeType, String identifierKey, Object identifierValue) {
String query = "MATCH (n:" + nodeType + " {" + identifierKey + ": $" + identifierKey + "}) DETACH DELETE n";
neo4jClient.query(query)
.bind(identifierValue).to(identifierKey)
.run();
}

public void createRelationship(String startNodeType, String startIdentifierKey, Object startIdentifierValue,
String endNodeType, String endIdentifierKey, Object endIdentifierValue,
String relationshipType) {
String query = "MATCH (a:" + startNodeType + " {" + startIdentifierKey + ": $" + startIdentifierKey + "}), " +
"(b:" + endNodeType + " {" + endIdentifierKey + ": $" + endIdentifierKey + "}) " +
"CREATE (a)-[r:" + relationshipType + "]->(b)";
neo4jClient.query(query)
.bind(startIdentifierValue).to(startIdentifierKey)
.bind(endIdentifierValue).to(endIdentifierKey)
.run();
}


public void updateRelationship(String startNodeType, String startIdentifierKey, Object startIdentifierValue,
String endNodeType, String endIdentifierKey, Object endIdentifierValue,
String relationshipType, Map<String, Object> properties) {
StringBuilder query = new StringBuilder("MATCH (a:" + startNodeType + " {" + startIdentifierKey + ": $" + startIdentifierKey + "}) " +
"-[r:" + relationshipType + "]->(b:" + endNodeType + " {" + endIdentifierKey + ": $" + endIdentifierKey + "}) SET ");
properties.forEach((key, value) -> query.append("r.").append(key).append(" = $").append(key).append(", "));
query.setLength(query.length() - 2); // 移除最后的逗号和空格

Neo4jClient.UnboundRunnableSpec neo4jQuery = neo4jClient.query(query.toString());
neo4jQuery.bind(startIdentifierValue).to(startIdentifierKey);
neo4jQuery.bind(endIdentifierValue).to(endIdentifierKey);
properties.forEach((key, value) -> neo4jQuery.bind(value).to(key));
neo4jQuery.run();
}


public void deleteRelationship(String startNodeType, String startIdentifierKey, Object startIdentifierValue,
String endNodeType, String endIdentifierKey, Object endIdentifierValue,
String relationshipType) {
String query = "MATCH (a:" + startNodeType + " {" + startIdentifierKey + ": $" + startIdentifierKey + "}) " +
"-[r:" + relationshipType + "]->(b:" + endNodeType + " {" + endIdentifierKey + ": $" + endIdentifierKey + "}) " +
"DELETE r";
neo4jClient.query(query)
.bind(startIdentifierValue).to(startIdentifierKey)
.bind(endIdentifierValue).to(endIdentifierKey)
.run();
}


public void clearDatabase(String dbName) {
neo4jClient.query("MATCH (n) DETACH DELETE n")
.bind(dbName).to("dbName") // 指定数据库
.run();
}

public boolean doesDatabaseExist(String dbName) {
String query = "CALL dbs() YIELD name WHERE name = $dbName RETURN name";
return neo4jClient.query(query)
.bind(dbName).to("dbName")
.fetchAs(String.class)
.mappedBy((type, record) -> record.get("name").asString())
.one()
.isPresent();
}

public boolean isValidAndExists(String dbName) {
return !doesDatabaseExist(dbName) && isValidDatabaseName(dbName);
}

public static String generateRandomDatabaseName() {
StringBuilder name = new StringBuilder(NAME_LENGTH);
// 首先添加一个字母
name.append(CHARACTERS.charAt(RANDOM.nextInt(52)));

// 随后添加随机字符
for (int i = 1; i < NAME_LENGTH; i++) {
name.append(CHARACTERS.charAt(RANDOM.nextInt(CHARACTERS.length())));
}

return name.toString();
}

public static boolean isValidDatabaseName(String name) {
// 检查长度
if (name == null || name.isEmpty() || name.length() > 255) {
return false;
}
// 检查首字符是否为字母
if (!Character.isLetter(name.charAt(0))) {
return false;
}
// 检查字符是否合法
for (char c : name.toCharArray()) {
if (!Character.isLetterOrDigit(c) && c != '_') {
return false;
}
}
return true;
}

}

+ 34
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/ExcelReader.java View File

@@ -0,0 +1,34 @@
package com.ruoyi.platform.utils;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;

import java.util.function.Consumer;

public class ExcelReader<T> {

private final String filePath;
private final Class<T> dataClass;
private final Consumer<T> processor;

public ExcelReader(String filePath, Class<T> dataClass, Consumer<T> processor) {
this.filePath = filePath;
this.dataClass = dataClass;
this.processor = processor;
}

public void read() {
EasyExcel.read(filePath, dataClass, new ReadListener<T>() {
@Override
public void invoke(T data, AnalysisContext context) {
processor.accept(data);
}

@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 所有数据处理完毕后的操作
}
}).sheet().doRead();
}
}

+ 35
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/ExcelReaderInputStream.java View File

@@ -0,0 +1,35 @@
package com.ruoyi.platform.utils;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;

import java.io.InputStream;
import java.util.function.Consumer;

public class ExcelReaderInputStream<T> {

private final InputStream inputStream;
private final Class<T> dataClass;
private final Consumer<T> processor;

public ExcelReaderInputStream(InputStream inputStream, Class<T> dataClass, Consumer<T> processor) {
this.inputStream = inputStream;
this.dataClass = dataClass;
this.processor = processor;
}

public void read() {
EasyExcel.read(inputStream, dataClass, new ReadListener<T>() {
@Override
public void invoke(T data, AnalysisContext context) {
processor.accept(data);
}

@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 所有数据处理完毕后的操作
}
}).sheet().doRead();
}
}

+ 14
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/MatKGVo.java View File

@@ -0,0 +1,14 @@
package com.ruoyi.platform.vo;

import lombok.Data;

@Data
public class MatKGVo {
private String Unnamed;
private String Entity;
private String Part_of_text;
private String NER_Tag;
private String DOI;
private String Preferred_Entity;
private Integer Year;
}

+ 52
- 0
ruoyi-modules/management-platform/src/test/java/com/ruoyi/platform/utils/ExcelReaderTest.java View File

@@ -0,0 +1,52 @@
package com.ruoyi.platform.utils;

import com.ruoyi.platform.domain.kg.*;
import com.ruoyi.platform.repository.MatKGRepository;
import com.ruoyi.platform.service.impl.MatKGServiceImpl;
import com.ruoyi.platform.vo.MatKGVo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ExcelReaderTest {
@Autowired
private MatKGServiceImpl service;

@Autowired
private MatKGRepository repository;
@Test
void read() {
String excelFilePath = "C:\\haha\\matKG\\ENTDOI.csv";

ExecutorService executorService = Executors.newFixedThreadPool(10);
// 创建ExcelReader实例
ExcelReader<MatKGVo> excelReader = new ExcelReader<>(excelFilePath, MatKGVo.class, data -> {
// Optional<MaterialEntity> existingEntity = service.findById(data.getEntity());
// executorService.execute(() -> {
MaterialEntity entity = new MaterialEntity();
entity.setId(data.getUnnamed());
entity.setEntity(data.getEntity());
entity.setPreferredEntity(new PreferredEntity(data.getPreferred_Entity()));
entity.setDoi(new DOI(data.getDOI(),data.getYear()));
entity.setNerTag(new NERTag(data.getNER_Tag()));
entity.setPartOfText(new PartOfText(data.getPart_of_text()));
service.save(entity);
// });
// System.out.println(data);
});

// 读取Excel文件
excelReader.read();
}

@Test
public void xx(){
Optional<MaterialEntity> byId = repository.findById("27358");
System.out.println(byId.get());
}
}

Loading…
Cancel
Save