mirror of
https://github.com/laurent22/joplin.git
synced 2025-01-05 12:50:29 +02:00
This commit is contained in:
parent
720494d870
commit
5082181c49
@ -257,22 +257,29 @@ describe('services_SearchEngine', function() {
|
|||||||
|
|
||||||
it('should support queries with Chinese characters', asyncTest(async () => {
|
it('should support queries with Chinese characters', asyncTest(async () => {
|
||||||
let rows;
|
let rows;
|
||||||
const n1 = await Note.save({ title: '我是法国人' });
|
const n1 = await Note.save({ title: '我是法国人', body: '中文测试' });
|
||||||
|
|
||||||
await engine.syncTables();
|
await engine.syncTables();
|
||||||
|
|
||||||
expect((await engine.search('我')).length).toBe(1);
|
expect((await engine.search('我')).length).toBe(1);
|
||||||
expect((await engine.search('法国人')).length).toBe(1);
|
expect((await engine.search('法国人')).length).toBe(1);
|
||||||
|
expect((await engine.search('法国人*'))[0].fields.sort()).toEqual(['body', 'title']); // usually assume that keyword was matched in body
|
||||||
|
expect((await engine.search('测试')).length).toBe(1);
|
||||||
|
expect((await engine.search('测试'))[0].fields).toEqual(['body']);
|
||||||
|
expect((await engine.search('测试*'))[0].fields).toEqual(['body']);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should support queries with Japanese characters', asyncTest(async () => {
|
it('should support queries with Japanese characters', asyncTest(async () => {
|
||||||
let rows;
|
let rows;
|
||||||
const n1 = await Note.save({ title: '私は日本語を話すことができません' });
|
const n1 = await Note.save({ title: '私は日本語を話すことができません', body: 'テスト' });
|
||||||
|
|
||||||
await engine.syncTables();
|
await engine.syncTables();
|
||||||
|
|
||||||
expect((await engine.search('日本')).length).toBe(1);
|
expect((await engine.search('日本')).length).toBe(1);
|
||||||
expect((await engine.search('できません')).length).toBe(1);
|
expect((await engine.search('できません')).length).toBe(1);
|
||||||
|
expect((await engine.search('できません*'))[0].fields.sort()).toEqual(['body', 'title']); // usually assume that keyword was matched in body
|
||||||
|
expect((await engine.search('テスト'))[0].fields.sort()).toEqual(['body']);
|
||||||
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should support queries with Korean characters', asyncTest(async () => {
|
it('should support queries with Korean characters', asyncTest(async () => {
|
||||||
@ -302,10 +309,15 @@ describe('services_SearchEngine', function() {
|
|||||||
await engine.syncTables();
|
await engine.syncTables();
|
||||||
|
|
||||||
expect((await engine.search('title:你好*')).length).toBe(1);
|
expect((await engine.search('title:你好*')).length).toBe(1);
|
||||||
|
expect((await engine.search('title:你好*'))[0].fields).toEqual(['title']);
|
||||||
|
expect((await engine.search('body:法国人')).length).toBe(1);
|
||||||
|
expect((await engine.search('body:法国人'))[0].fields).toEqual(['body']);
|
||||||
expect((await engine.search('body:你好')).length).toBe(0);
|
expect((await engine.search('body:你好')).length).toBe(0);
|
||||||
expect((await engine.search('title:你好 body:法国人')).length).toBe(1);
|
expect((await engine.search('title:你好 body:法国人')).length).toBe(1);
|
||||||
|
expect((await engine.search('title:你好 body:法国人'))[0].fields.sort()).toEqual(['body', 'title']);
|
||||||
expect((await engine.search('title:你好 body:bla')).length).toBe(0);
|
expect((await engine.search('title:你好 body:bla')).length).toBe(0);
|
||||||
expect((await engine.search('title:你好 我是')).length).toBe(1);
|
expect((await engine.search('title:你好 我是')).length).toBe(1);
|
||||||
|
expect((await engine.search('title:你好 我是'))[0].fields.sort()).toEqual(['body', 'title']);
|
||||||
expect((await engine.search('title:bla 我是')).length).toBe(0);
|
expect((await engine.search('title:bla 我是')).length).toBe(0);
|
||||||
|
|
||||||
// For non-alpha char, only the first field is looked at, the following ones are ignored
|
// For non-alpha char, only the first field is looked at, the following ones are ignored
|
||||||
|
@ -235,13 +235,36 @@ class SearchEngine {
|
|||||||
return occurenceCount / spread;
|
return occurenceCount / spread;
|
||||||
}
|
}
|
||||||
|
|
||||||
processResults_(rows, parsedQuery) {
|
processBasicSearchResults_(rows, parsedQuery) {
|
||||||
|
const valueRegexs = parsedQuery.keys.includes('_') ? parsedQuery.terms['_'].map(term => term.valueRegex || term.value) : [];
|
||||||
|
const isTitleSearch = parsedQuery.keys.includes('title');
|
||||||
|
const isOnlyTitle = parsedQuery.keys.length === 1 && isTitleSearch;
|
||||||
|
|
||||||
|
for (let i = 0; i < rows.length; i++) {
|
||||||
|
const row = rows[i];
|
||||||
|
const testTitle = regex => new RegExp(regex, 'ig').test(row.title);
|
||||||
|
const matchedFields = {
|
||||||
|
title: isTitleSearch || valueRegexs.some(testTitle),
|
||||||
|
body: !isOnlyTitle,
|
||||||
|
};
|
||||||
|
|
||||||
|
row.fields = Object.keys(matchedFields).filter(key => matchedFields[key]);
|
||||||
|
row.weight = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
processResults_(rows, parsedQuery, isBasicSearchResults = false) {
|
||||||
|
if (isBasicSearchResults) {
|
||||||
|
this.processBasicSearchResults_(rows, parsedQuery);
|
||||||
|
} else {
|
||||||
for (let i = 0; i < rows.length; i++) {
|
for (let i = 0; i < rows.length; i++) {
|
||||||
const row = rows[i];
|
const row = rows[i];
|
||||||
const offsets = row.offsets.split(' ').map(o => Number(o));
|
const offsets = row.offsets.split(' ').map(o => Number(o));
|
||||||
row.weight = this.calculateWeight_(offsets, parsedQuery.termCount);
|
row.weight = this.calculateWeight_(offsets, parsedQuery.termCount);
|
||||||
row.fields = this.fieldNamesFromOffsets_(offsets);
|
row.fields = this.fieldNamesFromOffsets_(offsets);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
rows.sort((a, b) => {
|
rows.sort((a, b) => {
|
||||||
if (a.fields.includes('title') && !b.fields.includes('title')) return -1;
|
if (a.fields.includes('title') && !b.fields.includes('title')) return -1;
|
||||||
@ -383,6 +406,8 @@ class SearchEngine {
|
|||||||
const searchOptions = {};
|
const searchOptions = {};
|
||||||
|
|
||||||
for (const key of parsedQuery.keys) {
|
for (const key of parsedQuery.keys) {
|
||||||
|
if (parsedQuery.terms[key].length === 0) continue;
|
||||||
|
|
||||||
const term = parsedQuery.terms[key][0].value;
|
const term = parsedQuery.terms[key][0].value;
|
||||||
if (key === '_') searchOptions.anywherePattern = `*${term}*`;
|
if (key === '_') searchOptions.anywherePattern = `*${term}*`;
|
||||||
if (key === 'title') searchOptions.titlePattern = `*${term}*`;
|
if (key === 'title') searchOptions.titlePattern = `*${term}*`;
|
||||||
@ -415,10 +440,13 @@ class SearchEngine {
|
|||||||
query = this.normalizeText_(query);
|
query = this.normalizeText_(query);
|
||||||
|
|
||||||
const searchType = this.determineSearchType_(query, options.searchType);
|
const searchType = this.determineSearchType_(query, options.searchType);
|
||||||
|
const parsedQuery = this.parseQuery(query);
|
||||||
|
|
||||||
if (searchType === SearchEngine.SEARCH_TYPE_BASIC) {
|
if (searchType === SearchEngine.SEARCH_TYPE_BASIC) {
|
||||||
// Non-alphabetical languages aren't support by SQLite FTS (except with extensions which are not available in all platforms)
|
// Non-alphabetical languages aren't support by SQLite FTS (except with extensions which are not available in all platforms)
|
||||||
return this.basicSearch(query);
|
const rows = await this.basicSearch(query);
|
||||||
|
this.processResults_(rows, parsedQuery, true);
|
||||||
|
return rows;
|
||||||
} else { // SEARCH_TYPE_FTS
|
} else { // SEARCH_TYPE_FTS
|
||||||
// FTS will ignore all special characters, like "-" in the index. So if
|
// FTS will ignore all special characters, like "-" in the index. So if
|
||||||
// we search for "this-phrase" it won't find it because it will only
|
// we search for "this-phrase" it won't find it because it will only
|
||||||
@ -426,7 +454,6 @@ class SearchEngine {
|
|||||||
// when searching.
|
// when searching.
|
||||||
// https://github.com/laurent22/joplin/issues/1075#issuecomment-459258856
|
// https://github.com/laurent22/joplin/issues/1075#issuecomment-459258856
|
||||||
query = query.replace(/-/g, ' ');
|
query = query.replace(/-/g, ' ');
|
||||||
const parsedQuery = this.parseQuery(query);
|
|
||||||
const sql = `
|
const sql = `
|
||||||
SELECT
|
SELECT
|
||||||
notes_fts.id,
|
notes_fts.id,
|
||||||
|
Loading…
Reference in New Issue
Block a user