mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-07-24 17:31:52 +00:00
[ACA-2219] support more precise searching (#976)
* support more precise searching * exact term matching * remove fdescribe * update docs
This commit is contained in:
committed by
Cilibiu Bogdan
parent
f25eef599d
commit
f58b6e5a9f
@@ -35,11 +35,16 @@ describe('SearchComponent', () => {
|
||||
expect(component.formatSearchQuery('')).toBeNull();
|
||||
});
|
||||
|
||||
it('should use original user input if content contains colons', () => {
|
||||
it('should use original user input if text contains colons', () => {
|
||||
const query = 'TEXT:test OR TYPE:folder';
|
||||
expect(component.formatSearchQuery(query)).toBe(query);
|
||||
});
|
||||
|
||||
it('should use original user input if text contains quotes', () => {
|
||||
const query = `"Hello World"`;
|
||||
expect(component.formatSearchQuery(query)).toBe(query);
|
||||
});
|
||||
|
||||
it('should format user input according to the configuration fields', () => {
|
||||
config.config = {
|
||||
search: {
|
||||
@@ -48,7 +53,7 @@ describe('SearchComponent', () => {
|
||||
};
|
||||
|
||||
const query = component.formatSearchQuery('hello');
|
||||
expect(query).toBe(`cm:name:"hello*" OR cm:title:"hello*"`);
|
||||
expect(query).toBe(`(cm:name:"hello*" OR cm:title:"hello*")`);
|
||||
});
|
||||
|
||||
it('should format user input as cm:name if configuration not provided', () => {
|
||||
@@ -59,7 +64,75 @@ describe('SearchComponent', () => {
|
||||
};
|
||||
|
||||
const query = component.formatSearchQuery('hello');
|
||||
expect(query).toBe(`cm:name:"hello*"`);
|
||||
expect(query).toBe(`(cm:name:"hello*")`);
|
||||
});
|
||||
|
||||
it('should use AND operator when conjunction has no operators', () => {
|
||||
config.config = {
|
||||
search: {
|
||||
'aca:fields': ['cm:name']
|
||||
}
|
||||
};
|
||||
|
||||
const query = component.formatSearchQuery('big yellow banana');
|
||||
|
||||
expect(query).toBe(
|
||||
`(cm:name:"big*") AND (cm:name:"yellow*") AND (cm:name:"banana*")`
|
||||
);
|
||||
});
|
||||
|
||||
it('should support conjunctions with AND operator', () => {
|
||||
config.config = {
|
||||
search: {
|
||||
'aca:fields': ['cm:name', 'cm:title']
|
||||
}
|
||||
};
|
||||
|
||||
const query = component.formatSearchQuery('big AND yellow AND banana');
|
||||
|
||||
expect(query).toBe(
|
||||
`(cm:name:"big*" OR cm:title:"big*") AND (cm:name:"yellow*" OR cm:title:"yellow*") AND (cm:name:"banana*" OR cm:title:"banana*")`
|
||||
);
|
||||
});
|
||||
|
||||
it('should support conjunctions with OR operator', () => {
|
||||
config.config = {
|
||||
search: {
|
||||
'aca:fields': ['cm:name', 'cm:title']
|
||||
}
|
||||
};
|
||||
|
||||
const query = component.formatSearchQuery('big OR yellow OR banana');
|
||||
|
||||
expect(query).toBe(
|
||||
`(cm:name:"big*" OR cm:title:"big*") OR (cm:name:"yellow*" OR cm:title:"yellow*") OR (cm:name:"banana*" OR cm:title:"banana*")`
|
||||
);
|
||||
});
|
||||
|
||||
it('should support exact term matching with default fields', () => {
|
||||
config.config = {
|
||||
search: {
|
||||
'aca:fields': ['cm:name', 'cm:title']
|
||||
}
|
||||
};
|
||||
|
||||
const query = component.formatSearchQuery('=orange');
|
||||
|
||||
expect(query).toBe(`(=cm:name:"orange" OR =cm:title:"orange")`);
|
||||
});
|
||||
|
||||
it('should support exact term matching with operators', () => {
|
||||
config.config = {
|
||||
search: {
|
||||
'aca:fields': ['cm:name', 'cm:title']
|
||||
}
|
||||
};
|
||||
|
||||
const query = component.formatSearchQuery('=test1.pdf or =test2.pdf');
|
||||
|
||||
expect(query).toBe(
|
||||
`(=cm:name:"test1.pdf" OR =cm:title:"test1.pdf") or (=cm:name:"test2.pdf" OR =cm:title:"test2.pdf")`
|
||||
);
|
||||
});
|
||||
|
||||
it('should navigate to folder on double click', () => {
|
||||
|
@@ -114,6 +114,33 @@ export class SearchResultsComponent extends PageComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
private isOperator(input: string): boolean {
|
||||
if (input) {
|
||||
input = input.trim().toUpperCase();
|
||||
|
||||
const operators = ['AND', 'OR'];
|
||||
return operators.includes(input);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private formatFields(fields: string[], term: string): string {
|
||||
let prefix = '';
|
||||
let suffix = '*';
|
||||
|
||||
if (term.startsWith('=')) {
|
||||
prefix = '=';
|
||||
suffix = '';
|
||||
term = term.substring(1);
|
||||
}
|
||||
|
||||
return (
|
||||
'(' +
|
||||
fields.map(field => `${prefix}${field}:"${term}${suffix}"`).join(' OR ') +
|
||||
')'
|
||||
);
|
||||
}
|
||||
|
||||
formatSearchQuery(userInput: string) {
|
||||
if (!userInput) {
|
||||
return null;
|
||||
@@ -121,14 +148,28 @@ export class SearchResultsComponent extends PageComponent implements OnInit {
|
||||
|
||||
userInput = userInput.trim();
|
||||
|
||||
if (userInput.includes(':')) {
|
||||
if (userInput.includes(':') || userInput.includes('"')) {
|
||||
return userInput;
|
||||
}
|
||||
|
||||
const fields = this.config.get<string[]>('search.aca:fields', ['cm:name']);
|
||||
const query = fields.map(field => `${field}:"${userInput}*"`).join(' OR ');
|
||||
const words = userInput.split(' ');
|
||||
|
||||
return query;
|
||||
if (words.length > 1) {
|
||||
const separator = words.some(this.isOperator) ? ' ' : ' AND ';
|
||||
|
||||
return words
|
||||
.map(term => {
|
||||
if (this.isOperator(term)) {
|
||||
return term;
|
||||
}
|
||||
|
||||
return this.formatFields(fields, term);
|
||||
})
|
||||
.join(separator);
|
||||
}
|
||||
|
||||
return this.formatFields(fields, userInput);
|
||||
}
|
||||
|
||||
onSearchResultLoaded(nodePaging: NodePaging) {
|
||||
|
Reference in New Issue
Block a user