Moved slot filler search to server side, limited docs in subscription

This commit is contained in:
Stefan Zermatten
2021-02-11 22:09:43 +02:00
parent 8c477ad4b1
commit dcb535c84e
5 changed files with 123 additions and 49 deletions

View File

@@ -53,3 +53,4 @@ peerlibrary:reactive-publish
simple:rest
simple:rest-method-mixin
mikowals:batch-insert
peerlibrary:subscription-data

View File

@@ -95,11 +95,15 @@ ongoworks:speakingurl@9.0.0
ordered-dict@1.1.0
patreon-oauth@0.1.0
peerlibrary:assert@0.3.0
peerlibrary:check-extension@0.7.0
peerlibrary:computed-field@0.10.0
peerlibrary:data-lookup@0.3.0
peerlibrary:extend-publish@0.6.0
peerlibrary:fiber-utils@0.10.0
peerlibrary:reactive-mongo@0.4.0
peerlibrary:reactive-publish@0.10.0
peerlibrary:server-autorun@0.8.0
peerlibrary:subscription-data@0.8.0
percolate:migrations@0.9.8
percolate:synced-cron@1.3.2
promise@0.11.2

View File

@@ -32,6 +32,14 @@ let LibraryNodeSchema = new SimpleSchema({
}
});
// Set up server side search index
if (Meteor.isServer) {
LibraryNodes._ensureIndex({
'name': 'text',
'tags': 'text',
});
}
for (let key in propertySchemasIndex){
let schema = new SimpleSchema({});
schema.extend(LibraryNodeSchema);

View File

@@ -1,8 +1,10 @@
import { check } from 'meteor/check';
import Libraries from '/imports/api/library/Libraries.js';
import LibraryNodes from '/imports/api/library/LibraryNodes.js';
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
Meteor.publish('slotFillers', function(slotId){
let self = this;
this.autorun(function (){
let userId = this.userId;
if (!userId) {
@@ -46,6 +48,44 @@ Meteor.publish('slotFillers', function(slotId){
slotFillerType: slot.slotType,
}];
}
return LibraryNodes.find(filter);
this.autorun(function(){
// Get the limit of the documents the user can fetch
var limit = self.data('limit') || 16;
check(limit, Number);
// Get the search term
let searchTerm = self.data('searchTerm') || '';
check(searchTerm, String);
let options = undefined;
if (searchTerm){
filter.$text = {$search: searchTerm};
options = {
// relevant documents have a higher score.
fields: {
score: { $meta: 'textScore' }
},
sort: {
// `score` property specified in the projection fields above.
score: { $meta: 'textScore' },
name: 1,
order: 1,
}
}
} else {
options = {sort: {
name: 1,
order: 1,
}};
}
options.limit = limit;
self.autorun(function () {
self.setData('countAll', LibraryNodes.find(filter).count());
});
self.autorun(function () {
return LibraryNodes.find(filter, options);
});
});
});
});

View File

@@ -13,7 +13,7 @@
regular
hide-details
:value="searchValue"
:debounce="200"
:debounce="300"
@change="searchChanged"
@keyup.enter="insert"
/>
@@ -22,49 +22,60 @@
class="library-nodes"
>
<v-fade-transition mode="out-in">
<column-layout
v-if="$subReady.slotFillers && libraryNodes && libraryNodes.length"
wide-columns
>
<div
v-for="node in libraryNodes"
:key="node._id"
<div v-if="libraryNodes && libraryNodes.length">
<column-layout
wide-columns
>
<v-card
hover
ripple
class="slot-card"
:class="{'primary': node._id === (selectedNode && selectedNode._id)}"
:dark="node._id === (selectedNode && selectedNode._id)"
@click="selectedNode = node"
<div
v-for="node in libraryNodes"
:key="node._id"
>
<v-img
v-if="node.picture"
:src="node.picture"
:height="200"
contain
/>
<v-card-title primary-title>
<div>
<h3 class="title mb-0">
<tree-node-view
class="mr-2"
:class="{'theme--dark': node._id === (selectedNode && selectedNode._id)}"
:hide-icon="node.picture"
:model="node"
:color="node.color"
<v-card
hover
ripple
class="slot-card"
:class="{'primary': node._id === (selectedNode && selectedNode._id)}"
:dark="node._id === (selectedNode && selectedNode._id)"
@click="selectedNode = node"
>
<v-img
v-if="node.picture"
:src="node.picture"
:height="200"
contain
/>
<v-card-title primary-title>
<div>
<h3 class="title mb-0">
<tree-node-view
class="mr-2"
:class="{'theme--dark': node._id === (selectedNode && selectedNode._id)}"
:hide-icon="node.picture"
:model="node"
:color="node.color"
/>
</h3>
<property-description
:string="model.description"
:calculations="model.descriptionCalculations"
:inactive="model.inactive"
/>
</h3>
<property-description
:string="model.description"
:calculations="model.descriptionCalculations"
:inactive="model.inactive"
/>
</div>
</v-card-title>
</v-card>
</div>
</v-card-title>
</v-card>
</div>
</column-layout>
<div class="layout row justify-center">
<v-btn
v-if="currentLimit < countAll"
:loading="!$subReady.slotFillers"
class="primary"
@click="loadMore"
>
Load More
</v-btn>
</div>
</column-layout>
</div>
<div
v-else-if="$subReady.slotFillers"
class="ma-4"
@@ -94,8 +105,10 @@
</span>
</p>
</div>
</v-fade-transition>
<v-fade-transition mode="out-in">
<div
v-else
v-if="!$subReady.slotFillers"
key="character-loading"
class="fill-height layout justify-center align-center"
>
@@ -179,10 +192,16 @@ export default {
return prop && prop.name;
},
searchChanged(val, ack){
this._subs['slotFillers'].setData('searchTerm', val);
this._subs['slotFillers'].setData('limit', undefined);
this.selectedNode = undefined;
this.searchValue = val;
setTimeout(ack, 200);
},
loadMore(){
if (this.currentLimit >= this.countAll) return;
this._subs['slotFillers'].setData('limit', this.currentLimit + 16);
},
insert(){
if (!this.selectedNode) return;
this.$store.dispatch('popDialogStack', this.selectedNode);
@@ -200,16 +219,16 @@ export default {
creature(){
return Creatures.findOne(this.creatureId);
},
currentLimit(){
return this._subs['slotFillers'].data('limit') || 16;
},
countAll(){
return this._subs['slotFillers'].data('countAll');
},
libraryNodes(){
let filter = {
removed: {$ne: true},
};
if (this.searchValue){
filter.name = {
$regex: this.searchValue.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'),
$options: 'i'
};
}
if (this.model.slotTags && this.model.slotTags.length){
filter.tags = {$all: this.model.slotTags};
}
@@ -221,7 +240,9 @@ export default {
slotFillerType: this.model.slotType,
}];
}
let nodes = LibraryNodes.find(filter).fetch();
let nodes = LibraryNodes.find(filter, {
sort: {name: 1, order: 1}
}).fetch();
// Filter out slotFillers whose condition isn't met or are too big to fit
// the quantity to fill
nodes = nodes.filter(node => {