mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-11-04 15:11:31 +08:00 
			
		
		
		
	ETAPI search endpoint
This commit is contained in:
		
							parent
							
								
									c5366abf75
								
							
						
					
					
						commit
						c33bc7e12c
					
				@ -5,8 +5,24 @@ const mappers = require("./mappers");
 | 
				
			|||||||
const noteService = require("../services/notes");
 | 
					const noteService = require("../services/notes");
 | 
				
			||||||
const TaskContext = require("../services/task_context");
 | 
					const TaskContext = require("../services/task_context");
 | 
				
			||||||
const validators = require("./validators");
 | 
					const validators = require("./validators");
 | 
				
			||||||
 | 
					const searchService = require("../services/search/services/search");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function register(router) {
 | 
					function register(router) {
 | 
				
			||||||
 | 
					    ru.route(router, 'get', '/etapi/notes', (req, res, next) => {
 | 
				
			||||||
 | 
					        const {search} = req.query;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!search?.trim()) {
 | 
				
			||||||
 | 
					            throw new ru.EtapiError(400, 'SEARCH_QUERY_PARAM_MANDATORY', "'search' query parameter is mandatory");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        const searchParams = parseSearchParams(req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const foundNotes = searchService.searchNotes(search, searchParams);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        console.log(foundNotes.map(note => mappers.mapNoteToPojo(note)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        res.json(foundNotes.map(note => mappers.mapNoteToPojo(note)));
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ru.route(router, 'get', '/etapi/notes/:noteId', (req, res, next) => {
 | 
					    ru.route(router, 'get', '/etapi/notes/:noteId', (req, res, next) => {
 | 
				
			||||||
        const note = ru.getAndCheckNote(req.params.noteId);
 | 
					        const note = ru.getAndCheckNote(req.params.noteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -85,6 +101,71 @@ function register(router) {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function parseSearchParams(req) {
 | 
				
			||||||
 | 
					    const rawSearchParams = {
 | 
				
			||||||
 | 
					        'fastSearch': parseBoolean(req.query, 'fastSearch'),
 | 
				
			||||||
 | 
					        'includeArchivedNotes': parseBoolean(req.query, 'includeArchivedNotes'),
 | 
				
			||||||
 | 
					        'ancestorNoteId': req.query['ancestorNoteId'],
 | 
				
			||||||
 | 
					        'ancestorDepth': parseInteger(req.query, 'ancestorDepth'),
 | 
				
			||||||
 | 
					        'orderBy': req.query['orderBy'],
 | 
				
			||||||
 | 
					        'orderDirection': parseOrderDirection(req.query, 'orderDirection'),
 | 
				
			||||||
 | 
					        'limit': parseInteger(req.query, 'limit'),
 | 
				
			||||||
 | 
					        'debug': parseBoolean(req.query, 'debug')
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const searchParams = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (const paramName of Object.keys(rawSearchParams)) {
 | 
				
			||||||
 | 
					        if (rawSearchParams[paramName] !== undefined) {
 | 
				
			||||||
 | 
					            searchParams[paramName] = rawSearchParams[paramName];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return searchParams;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const SEARCH_PARAM_ERROR = "SEARCH_PARAM_VALIDATION_ERROR";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function parseBoolean(obj, name) {
 | 
				
			||||||
 | 
					    if (!(name in obj)) {
 | 
				
			||||||
 | 
					        return undefined;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!['true', 'false'].includes(obj[name])) {
 | 
				
			||||||
 | 
					        throw new ru.EtapiError(400, SEARCH_PARAM_ERROR, `Cannot parse boolean '${name}' value '${obj[name]}, allowed values are 'true' and 'false'`);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return obj[name] === 'true';
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function parseInteger(obj, name) {
 | 
				
			||||||
 | 
					    if (!(name in obj)) {
 | 
				
			||||||
 | 
					        return undefined;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const integer = parseInt(obj[name]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!['asc', 'desc'].includes(obj[name])) {
 | 
				
			||||||
 | 
					        throw new ru.EtapiError(400, SEARCH_PARAM_ERROR, `Cannot parse order direction value '${obj[name]}, allowed values are 'asc' and 'desc'`);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return integer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function parseOrderDirection(obj, name) {
 | 
				
			||||||
 | 
					    if (!(name in obj)) {
 | 
				
			||||||
 | 
					        return undefined;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const integer = parseInt(obj[name]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (Number.isNaN(integer)) {
 | 
				
			||||||
 | 
					        throw new ru.EtapiError(400, SEARCH_PARAM_ERROR, `Cannot parse integer '${name}' value '${obj[name]}`);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return integer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					module.exports = {
 | 
				
			||||||
    register
 | 
					    register
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										35
									
								
								test-etapi/search.http
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								test-etapi/search.http
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					POST {{triliumHost}}/etapi/create-note
 | 
				
			||||||
 | 
					Content-Type: application/json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  "parentNoteId": "root",
 | 
				
			||||||
 | 
					  "title": "title",
 | 
				
			||||||
 | 
					  "type": "text",
 | 
				
			||||||
 | 
					  "content": "{{$uuid}}"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> {% client.global.set("createdNoteId", response.body.note.noteId); %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					###
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GET {{triliumHost}}/etapi/notes/{{createdNoteId}}/content
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> {% client.global.set("content", response.body); %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					###
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GET {{triliumHost}}/etapi/notes?search={{content}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> {%
 | 
				
			||||||
 | 
					client.assert(response.status === 200);
 | 
				
			||||||
 | 
					client.assert(response.body.length === 1);
 | 
				
			||||||
 | 
					%}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Same but with fast search which doesn't look in the content so 0 notes should be found
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GET {{triliumHost}}/etapi/notes?search={{content}}&fastSearch=true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> {%
 | 
				
			||||||
 | 
					client.assert(response.status === 200);
 | 
				
			||||||
 | 
					client.assert(response.body.length === 0);
 | 
				
			||||||
 | 
					%}
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user