- N-gram은 통계학 기반의 언어 모델 중 하나로, 텍스트나 연설에서 N개의 연속적인 항목(문자, 음절, 단어 등)의 시퀀스를 말합니다. 'N'은 숫자를 나타내며, 문자열을 일정한 길이 N으로 끊어서 중복되게 분할하는 방법입니다.
추천: 2~3글자 단위 N-gram (bi-gram/tri-gram)
- 2~3자 조합만 포함,단일 글자는 제외,
- 검색어가 길든 짧든 일정한 기준으로 매칭 가능
- 중간 글자 검색도 가능
예: "히포에스테스"
2-gram → ["히포", "포에", "에스", "스테", "테스"]
3-gram → ["히포에", "포에스", "에스테", "스테스"]
N-Gram 생성 코드
List<String> _generateNGrams(String input) { // 1. 공백 제거 final normalized = input.replaceAll(' ', ''); // 2. 중복을 허용하지 않는 컬렉션 Set 생성 final ngrams = <String>{}; // 3. 2~3글자 단위로 N-gram 생성 for (int n = 2; n <= 3; n++) { for (int i = 0; i <= normalized.length - n; i++) { // 4. n개씩 잘라서 추가 ngrams.add(normalized.substring(i, i + n)); } } // 5. Set → List로 변환 return ngrams.toList(); }
substring(start, end)
- start: 시작 인덱스 (포함)
- end: 끝 인덱스 (불포함) ← 중요!
final data = doc.data();
- 해당 문서 안에 있는 모든 필드를 Map<String, dynamic> 형태로 가져오는 것
{ 'contentNum': '18657', 'plantName': '얼록자주달개비', 'photoFileUrl': 'https://...', 'createdAt': 1749982130382 }
전체 코드
Future<void> updatePlantsWithNGrams() async { DocumentSnapshot? lastDoc; while (true) { // 1. 데이터 가져오기 final query = _plantsCollection.limit(10); final snapshot = lastDoc == null ? await query.get() : await query.startAfterDocument(lastDoc).get(); if (snapshot.docs.isEmpty) break; // Firestore에서 여러 개의 .set(), .update(), .delete() 작업을 한 번에 처리하는 트랜잭션 비슷한 묶음 final batch = FirebaseFirestore.instance.batch(); for (final doc in snapshot.docs) { final data = doc.data(); final plantName = data['plantName'] ?? ''; final ngrams = _generateNGrams(plantName); // 2. Firestore에 ngrams 필드 업데이트 batch.update(doc.reference, {'ngrams': ngrams}); } // 3. 한꺼번에 commit 완료 await batch.commit(); lastDoc = snapshot.docs.last; } print('모든 문서에 ngrams 필드 추가 완료'); }