본문 바로가기

개발중/Spring

쿼리 생성 API 고민하기.

728x90
반응형

쿼리를 생성해야 하는데 ,.

일반 쿼리 / 구문 쿼리 / 인접 쿼리 / 제외 쿼리를 각각의 쿼리로 만들다 보니깐.

엥 ? 겹치는 기능들이 너무 많아. 


일반 쿼리 생성 - 조합시 OR 

EX ) ("영양정보") OR ("탄수" AND "화물") OR ("당류") OR ("영양소")

public String createBasicKeyword( String beforeKeyword ) {
	
	/*
	 *  키워드 구분
	 *  개행을 기준으로 줄 바꿈을 진행 합니다.
	 */
	String[] keywordList = beforeKeyword.split("\n");
	String[] wordList;
	Stream<String> stream;
	int index = 0;
	
	/*
	 * 키워드 가공
	 * - 띄어쓰기가 있다면 
	 *    - 큰따옴표로 감싼 후 AND 절로 조인
	 * - 띄어쓰기가 없다면 
	 *    - 큰따옴표로 감싸기
	 */
	for (String keyword : keywordList) {
		wordList = keyword.split(" ");
		stream = Arrays.stream(wordList);
		keywordList[index++] = stream.map(name -> "\"" + name + "\"" ).collect(Collectors.joining(wordList.length > 1 ? " AND " : ""));
	}

	/*
	 * 키워드 조합
	 * - 키워드를 () 로 감싼 후 OR 절로 조인
	 */
	stream = Arrays.stream(keywordList);
	return stream.map( name -> "(" + name + ")" ).collect(Collectors.joining(" OR "));
}

구문 쿼리 생성 - 조합시 OR

EX ) (("연어") OR ("소고기") OR ("돼지 고기") OR ("삼치")) 

 

private String createExclusionKeyword( String beforeKeyword ) {
	/*
	 *  키워드 구분
	 *  개행을 기준으로 줄 바꿈을 진행 합니다.
	 */
	String[] keywordList = beforeKeyword.split("\n");
	Stream<String> stream; 
	
	/*
	 * 키워드 조합
	 * - 키워드를 () 로 감싼 후 OR 절로 조인
	 */
	stream = Arrays.stream(keywordList);
	return stream.map( name -> "(\"" + name + "\")" ).collect(Collectors.joining(" OR "));
}

인접 쿼리 생성 - 조합시 OR 

EX : ("시금치"~15) OR ("호밀빵"~15) OR ("그릭 요거트"~15)

private String createNearKeyword( String beforeKeyword ) {
	
	/*
	 *  키워드 구분
	 *  개행을 기준으로 줄 바꿈을 진행 합니다.
	 */
	String[] keywordList = beforeKeyword.split("\n");
	Stream<String> stream; 
	
	/*
	 * 키워드 조합
	 * - 키워드를 () 로 감싼 후 OR 절로 조인
	 */
	stream = Arrays.stream(keywordList);
	return stream.map( name -> "(\"" + name + "\"~15)" ).collect(Collectors.joining(" OR "));
}

제외 쿼리 생성 - 조합시 NOT

EX :  (("초콜릿") OR ("사탕") OR ("탄산" AND "음료"))

 

private String createExcludeKeyword( String beforeKeyword ) {
	
	/*
	 *  키워드 구분
	 *  개행을 기준으로 줄 바꿈을 진행 합니다.
	 */
	String[] keywordList = beforeKeyword.split("\n");
	Stream<String> stream; 
	
	/*
	 * 키워드 조합
	 * - 키워드를 () 로 감싼 후 OR 절로 조인
	 */
	stream = Arrays.stream(keywordList);
	return stream.map( name -> "(\"" + name + "\")" ).collect(Collectors.joining(" OR "));
}

수정 1

- 쿼리 만드는 애

/*
 * 쿼리 생성 
 */
public String createKeyword( keywordVo vo ) {

	if( vo.getBasicKeyword().equals("") || vo.getNearKeyword().equals("") || vo.getExclusionKeyword().equals("")) {
		throw new CustomException(ApiResultErrorCode.FieldValueException, "일반, 구문, 인접 키워드를 한개 이상 입력하여야 합니다.");
	}
	
	// 일반 키워드 생성
	String basicKeyword = createQueryOne(vo.getBasicKeyword());
	
	// 구문 키워드 생성
	String exclusionKeyword = createQueryTwo(vo.getExclusionKeyword(), "(\"", "\")");

	// 인접 키워드 생성
	String nearKeyword = createQueryTwo(vo.getNearKeyword(), "(\"", "\"~15)");

	// 제외 키워드 생성
	String excludeKeyword = createQueryOne(vo.getExcludeKeyword());
	
	String query = "(" +
				   createBracket(basicKeyword) + 
				   " OR " +
				   createBracket(exclusionKeyword) + 
				   " OR " +
				   createBracket(nearKeyword) + 
				   ")" + 
				   " NOT " +
				   createBracket(excludeKeyword);
	return query.replaceAll("\n", "");
}

 

- 키워드마다 띄어쓰기 AND 로 구분 하는 애

/**
 * 이용 키워드 : 일반 키워드
 */
private String createQueryOne( String beforeKeyword ) {
	
	/*
	 *  키워드 구분
	 *  개행을 기준으로 줄 바꿈을 진행 합니다.
	 */
	String[] keywordList = beforeKeyword.split("\n");
	String[] wordList;
	Stream<String> stream;
	int index = 0;
	
	/*
	 * 키워드 가공
	 * - 띄어쓰기가 있다면 
	 *    - 큰따옴표로 감싼 후 AND 절로 조인
	 * - 띄어쓰기가 없다면 
	 *    - 큰따옴표로 감싸기
	 */
	for (String keyword : keywordList) {
		wordList = keyword.split(" ");
		stream = Arrays.stream(wordList);
		keywordList[index++] = stream.map(name -> "\"" + name + "\"" ).collect(Collectors.joining(wordList.length > 1 ? " AND " : ""));
	}

	/*
	 * 키워드 조합
	 * - 키워드를 () 로 감싼 후 OR 절로 조인
	 */
	stream = Arrays.stream(keywordList);
	return stream.map( name -> "(" + name + ")" ).collect(Collectors.joining(" OR "));
}

 

- 키워드마다 띄어쓰기 신경 안쓰는 애

/**
 * 이용 키워드 : 구문 키워드, 인접 키워드, 제외 키워드
 */
private String createQueryTwo( String beforeKeyword, String beforeStr, String afterStr ) {
	/*
	 *  키워드 구분
	 *  개행을 기준으로 줄 바꿈을 진행 합니다.
	 */
	String[] keywordList = beforeKeyword.split("\n");
	Stream<String> stream; 
	
	/*
	 * 키워드 조합
	 * - 키워드를 () 로 감싼 후 OR 절로 조인
	 */
	stream = Arrays.stream(keywordList);
	return stream.map( name -> beforeStr + name + afterStr ).collect(Collectors.joining(" OR "));
}

결과


((("영양정보") OR ("탄수" AND "화물") OR ("당류") OR ("영양소")) OR (("연어") OR ("소고기") OR ("돼지 고기") OR ("삼치")) OR (("시금치"~15) OR ("호밀빵"~15) OR ("그릭 요거트"~15))) NOT (("초콜릿") OR ("사탕") OR ("탄산" AND "음료"))

 

결과는 잘 나왔지만 어떤 방식이 맞는걸까 고민하는 시간은 늘 짜증난다


 

728x90
반응형

'개발중 > Spring' 카테고리의 다른 글

@RequestParam Null 잡기  (0) 2021.05.26
MYBATIS 에서 LIKE 절 사용하기  (0) 2021.05.25
@RestController - @Api 에서 데이터 받는 법  (0) 2021.05.18
mysql / my batis 여러개 업데이트  (0) 2021.05.18
DB 여러계정 연동  (0) 2021.04.28