order by note size + attachments + revisions, closes #4295

This commit is contained in:
zadam 2023-10-02 22:02:25 +02:00
parent 62ccf798ee
commit 1261a06a30
9 changed files with 74 additions and 24 deletions

View File

@ -0,0 +1 @@
UPDATE attributes SET value = 'contentAndAttachmentsAndRevisionsSize' WHERE name = 'orderBy' AND value = 'noteSize';

View File

@ -132,11 +132,17 @@ class BNote extends AbstractBeccaEntity {
*/ */
this.contentSize = null; this.contentSize = null;
/** /**
* size of the content and note revision contents in bytes * size of the note content, attachment contents in bytes
* @type {int|null} * @type {int|null}
* @private * @private
*/ */
this.noteSize = null; this.contentAndAttachmentsSize = null;
/**
* size of the note content, attachment contents and revision contents in bytes
* @type {int|null}
* @private
*/
this.contentAndAttachmentsAndRevisionsSize = null;
/** /**
* number of note revisions for this note * number of note revisions for this note
* @type {int|null} * @type {int|null}

View File

@ -127,7 +127,8 @@ paths:
- targetRelationCount - targetRelationCount
- targetRelationCountIncludingLinks - targetRelationCountIncludingLinks
- contentSize - contentSize
- noteSize - contentAndAttachmentsSize
- contentAndAttachmentsAndRevisionsSize
- revisionCount - revisionCount
- name: orderDirection - name: orderDirection
in: query in: query

View File

@ -14,7 +14,8 @@ const TPL = `
<option value="dateCreated">Date created</option> <option value="dateCreated">Date created</option>
<option value="dateModified">Date of last modification</option> <option value="dateModified">Date of last modification</option>
<option value="contentSize">Note content size</option> <option value="contentSize">Note content size</option>
<option value="noteSize">Note content size including revisions</option> <option value="contentAndAttachmentsSize">Note content size including attachments</option>
<option value="contentAndAttachmentsAndRevisionsSize">Note content size including attachments and revisions</option>
<option value="revisionCount">Number of revisions</option> <option value="revisionCount">Number of revisions</option>
<option value="childrenCount">Number of children notes</option> <option value="childrenCount">Number of children notes</option>
<option value="parentCount">Number of clones</option> <option value="parentCount">Number of clones</option>

View File

@ -4,7 +4,7 @@ const build = require('./build');
const packageJson = require('../../package'); const packageJson = require('../../package');
const {TRILIUM_DATA_DIR} = require('./data_dir'); const {TRILIUM_DATA_DIR} = require('./data_dir');
const APP_DB_VERSION = 225; const APP_DB_VERSION = 226;
const SYNC_VERSION = 31; const SYNC_VERSION = 31;
const CLIPPER_PROTOCOL_VERSION = "1.0"; const CLIPPER_PROTOCOL_VERSION = "1.0";

View File

@ -56,9 +56,9 @@ class OrderByAndLimitExp extends Expression {
if (!valA && !valB) { if (!valA && !valB) {
// the attribute value is empty/zero in both notes so continue to the next order definition // the attribute value is empty/zero in both notes so continue to the next order definition
continue; continue;
} else if (!valB || valA < valB) { } else if (valA < valB) {
return smaller; return smaller;
} else if (!valA || valA > valB) { } else if (valA > valB) {
return larger; return larger;
} }
// else the values are equal and continue to next order definition // else the values are equal and continue to next order definition

View File

@ -31,7 +31,8 @@ const PROP_MAPPING = {
"targetrelationcount": "targetRelationCount", "targetrelationcount": "targetRelationCount",
"targetrelationcountincludinglinks": "targetRelationCountIncludingLinks", "targetrelationcountincludinglinks": "targetRelationCountIncludingLinks",
"contentsize": "contentSize", "contentsize": "contentSize",
"notesize": "noteSize", "contentandattachmentssize": "contentAndAttachmentsSize",
"contentandattachmentsandrevisionssize": "contentAndAttachmentsAndRevisionsSize",
"revisioncount": "revisionCount" "revisioncount": "revisionCount"
}; };
@ -48,7 +49,7 @@ class PropertyComparisonExp extends Expression {
this.comparedValue = comparedValue; // for DEBUG mode this.comparedValue = comparedValue; // for DEBUG mode
this.comparator = buildComparator(operator, comparedValue); this.comparator = buildComparator(operator, comparedValue);
if (['contentsize', 'notesize', 'revisioncount'].includes(this.propertyName)) { if (['contentsize', 'contentandattachmentssize', 'contentandattachmentsandrevisionssize', 'revisioncount'].includes(this.propertyName)) {
searchContext.dbLoadNeeded = true; searchContext.dbLoadNeeded = true;
} }
} }

View File

@ -92,48 +92,87 @@ function searchFromRelation(note, relationName) {
function loadNeededInfoFromDatabase() { function loadNeededInfoFromDatabase() {
const sql = require('../../sql'); const sql = require('../../sql');
for (const noteId in becca.notes) { const noteBlobs = {};
becca.notes[noteId].contentSize = 0;
becca.notes[noteId].noteSize = 0;
becca.notes[noteId].revisionCount = 0;
}
const noteContentLengths = sql.getRows(` const noteContentLengths = sql.getRows(`
SELECT SELECT
noteId, noteId,
blobId,
LENGTH(content) AS length LENGTH(content) AS length
FROM notes FROM notes
JOIN blobs USING(blobId) JOIN blobs USING(blobId)
WHERE notes.isDeleted = 0`); WHERE notes.isDeleted = 0`);
for (const {noteId, length} of noteContentLengths) { for (const {noteId, blobId, length} of noteContentLengths) {
if (!(noteId in becca.notes)) { if (!(noteId in becca.notes)) {
log.error(`Note ${noteId} not found in becca.`); log.error(`Note '${noteId}' not found in becca.`);
continue; continue;
} }
becca.notes[noteId].contentSize = length; becca.notes[noteId].contentSize = length;
becca.notes[noteId].noteSize = length; becca.notes[noteId].revisionCount = 0;
noteBlobs[noteId] = { [blobId]: length };
}
const attachmentContentLengths = sql.getRows(`
SELECT
ownerId AS noteId,
attachments.blobId,
LENGTH(content) AS length
FROM attachments
JOIN notes ON attachments.ownerId = notes.noteId
JOIN blobs ON attachments.blobId = blobs.blobId
WHERE attachments.isDeleted = 0
AND notes.isDeleted = 0`);
for (const {noteId, blobId, length} of attachmentContentLengths) {
if (!(noteId in becca.notes)) {
log.error(`Note '${noteId}' not found in becca.`);
continue;
}
if (!(noteId in noteBlobs)) {
log.error(`Did not find a '${noteId}' in the noteBlobs.`);
continue;
}
noteBlobs[noteId][blobId] = length;
}
for (const noteId in noteBlobs) {
becca.notes[noteId].contentAndAttachmentsSize = Object.values(noteBlobs[noteId]).reduce((acc, size) => acc + size, 0);
} }
const revisionContentLengths = sql.getRows(` const revisionContentLengths = sql.getRows(`
SELECT SELECT
noteId, noteId,
revisions.blobId,
LENGTH(content) AS length LENGTH(content) AS length
FROM notes FROM notes
JOIN revisions USING(noteId) JOIN revisions USING(noteId)
JOIN blobs USING(blobId) JOIN blobs ON revisions.blobId = blobs.blobId
WHERE notes.isDeleted = 0`); WHERE notes.isDeleted = 0`);
for (const {noteId, length} of revisionContentLengths) { for (const {noteId, blobId, length} of revisionContentLengths) {
if (!(noteId in becca.notes)) { if (!(noteId in becca.notes)) {
log.error(`Note ${noteId} not found in becca.`); log.error(`Note '${noteId}' not found in becca.`);
continue; continue;
} }
becca.notes[noteId].noteSize += length; if (!(noteId in noteBlobs)) {
log.error(`Did not find a '${noteId}' in the noteBlobs.`);
continue;
}
noteBlobs[noteId][blobId] = length;
becca.notes[noteId].revisionCount++; becca.notes[noteId].revisionCount++;
} }
for (const noteId in noteBlobs) {
becca.notes[noteId].contentAndAttachmentsAndRevisionsSize = Object.values(noteBlobs[noteId]).reduce((acc, size) => acc + size, 0);
}
} }
/** /**

View File

@ -27,7 +27,8 @@ const PROP_MAPPING = {
"targetrelationcount": "targetRelationCount", "targetrelationcount": "targetRelationCount",
"targetrelationcountincludinglinks": "targetRelationCountIncludingLinks", "targetrelationcountincludinglinks": "targetRelationCountIncludingLinks",
"contentsize": "contentSize", "contentsize": "contentSize",
"notesize": "noteSize", "contentandattachmentssize": "contentAndAttachmentsSize",
"contentandattachmentsandrevisionssize": "contentAndAttachmentsAndRevisionsSize",
"revisioncount": "revisionCount" "revisioncount": "revisionCount"
}; };
@ -42,7 +43,7 @@ class ValueExtractor {
this.propertyPath = ['note', 'relations', this.propertyPath[0].substr(1), ...this.propertyPath.slice(1, this.propertyPath.length)]; this.propertyPath = ['note', 'relations', this.propertyPath[0].substr(1), ...this.propertyPath.slice(1, this.propertyPath.length)];
} }
if (['contentsize', 'notesize', 'revisioncount'].includes(this.propertyPath[this.propertyPath.length - 1])) { if (['contentsize', 'contentandattachmentssize', 'contentandattachmentsandrevisionssize', 'revisioncount'].includes(this.propertyPath[this.propertyPath.length - 1])) {
searchContext.dbLoadNeeded = true; searchContext.dbLoadNeeded = true;
} }
} }