primary and secondary index fields

This commit is contained in:
Martin McKeaveney 2021-02-09 18:49:12 +00:00
parent 41bc7dbaf7
commit e599854b14
8 changed files with 105 additions and 61 deletions

View File

@ -232,7 +232,7 @@ export const getBackendUiStore = () => {
return state
})
},
saveField: ({ originalName, field, primaryDisplay = false }) => {
saveField: ({ originalName, field, primaryDisplay = false, indexes }) => {
store.update(state => {
// delete the original if renaming
// need to handle if the column had no name, empty string
@ -249,6 +249,10 @@ export const getBackendUiStore = () => {
state.draftTable.primaryDisplay = field.name
}
if (indexes) {
state.draftTable.indexes = indexes
}
state.draftTable.schema[field.name] = cloneDeep(field)
store.actions.tables.save(state.draftTable)
return state

View File

@ -1,5 +1,12 @@
<script>
import { Input, Button, TextButton, Select, Toggle } from "@budibase/bbui"
import {
Input,
Button,
Label,
TextButton,
Select,
Toggle,
} from "@budibase/bbui"
import { cloneDeep } from "lodash/fp"
import { backendUiStore } from "builderStore"
import { TableNames, UNEDITABLE_USER_FIELDS } from "constants"
@ -24,6 +31,7 @@
let primaryDisplay =
$backendUiStore.selectedTable.primaryDisplay == null ||
$backendUiStore.selectedTable.primaryDisplay === field.name
let indexes = [...($backendUiStore.selectedTable.indexes || [])]
let confirmDeleteDialog
let deletion
@ -41,6 +49,7 @@
originalName,
field,
primaryDisplay,
indexes,
})
return state
})
@ -79,8 +88,24 @@
}
}
function onChangeSearchable() {
function onChangePrimaryIndex(e) {
const enabled = e.target.checked
if (enabled) {
indexes[0] = field.name
} else {
indexes.shift()
indexes = indexes
}
}
function onChangeSecondaryIndex(e) {
const enabled = e.target.checked
if (enabled) {
indexes[1] = field.name
} else {
indexes.pop()
indexes = indexes
}
}
function confirmDelete() {
@ -124,10 +149,20 @@
on:change={onChangePrimaryDisplay}
thin
text="Use as table display column" />
<Label gray small>Search Indexes</Label>
<Toggle
bind:checked={field.searchable}
checked={indexes[0] === field.name}
disabled={indexes[1] === field.name}
on:change={onChangePrimaryIndex}
thin
text="Index for Search" />
text="Primary" />
<Toggle
checked={indexes[1] === field.name}
disabled={!indexes[0] || indexes[0] === field.name}
on:change={onChangeSecondaryIndex}
thin
text="Secondary" />
{/if}
{#if field.type === 'string'}

View File

@ -229,27 +229,8 @@ exports.fetchView = async function(ctx) {
}
}
exports.createIndex = async function(ctx) {
const appId = "app_1987903cf3604d459969c80cf17651a0"
const db = new CouchDB(appId)
const indexes = await db.getIndexes()
// ctx.body = await db.get("_design/search_ddoc")
ctx.body = await db.createIndex({
index: {
fields: ctx.request.body.fields,
name: "other_search_index",
ddoc: "search_ddoc",
type: "json",
},
})
// ctx.body = await db.getIndexes()
}
exports.search = async function(ctx) {
// const appId = ctx.user.appId
const appId = "app_1987903cf3604d459969c80cf17651a0"
const appId = ctx.user.appId
const db = new CouchDB(appId)
@ -260,20 +241,10 @@ exports.search = async function(ctx) {
query.tableId = ctx.params.tableId
// Paginating
// if (cursor) {
// if (backwards) {
// query._id = { $lte: cursor }
// } else {
// query._id = { $gte: cursor }
// }
// }
const response = await db.find({
selector: query,
limit: pageSize,
skip: pageSize * page,
// sort: ["_id"],
})
const rows = response.docs
@ -285,7 +256,6 @@ exports.search = async function(ctx) {
}
}
// ctx.body = response
ctx.body = await linkRows.attachLinkInfo(appId, rows)
}

View File

@ -7,6 +7,7 @@ const {
generateTableID,
generateRowID,
} = require("../../db/utils")
const { isEqual } = require("lodash/fp")
async function checkForColumnUpdates(db, oldTable, updatedTable) {
let updatedRows
@ -38,18 +39,6 @@ async function checkForColumnUpdates(db, oldTable, updatedTable) {
return updatedRows
}
async function updateSearchIndex(fields) {
console.log("Updating stuff")
const resp = await db.createIndex({
index: {
fields,
name: "search_index",
ddoc: "search_ddoc",
type: "json",
},
})
}
exports.fetch = async function(ctx) {
const db = new CouchDB(ctx.user.appId)
const body = await db.allDocs(
@ -140,6 +129,46 @@ exports.save = async function(ctx) {
const result = await db.post(tableToSave)
tableToSave._rev = result.rev
// create relevant search indexes
if (tableToSave.indexes && tableToSave.indexes.length > 0) {
const currentIndexes = await db.getIndexes()
const indexName = `search:${result.id}`
const existingIndex = currentIndexes.indexes.find(
existing => existing.name === indexName
)
if (existingIndex) {
const currentFields = existingIndex.def.fields.map(
field => Object.keys(field)[0]
)
// if index fields have changed, delete the original index
if (!isEqual(currentFields, tableToSave.indexes)) {
await db.deleteIndex(existingIndex)
// create/recreate the index with fields
await db.createIndex({
index: {
fields: tableToSave.indexes,
name: indexName,
ddoc: "search_ddoc",
type: "json",
},
})
}
} else {
// create/recreate the index with fields
await db.createIndex({
index: {
fields: tableToSave.indexes,
name: indexName,
ddoc: "search_ddoc",
type: "json",
},
})
}
}
ctx.eventEmitter &&
ctx.eventEmitter.emitTable(`table:save`, appId, tableToSave)

View File

@ -31,14 +31,9 @@ router
usage,
rowController.save
)
.post(
"/api/createindex",
// authorized(PermissionTypes.TABLE, PermissionLevels.READ),
rowController.createIndex
)
.post(
"/api/:tableId/rows/search",
// authorized(PermissionTypes.TABLE, PermissionLevels.READ),
authorized(PermissionTypes.TABLE, PermissionLevels.READ),
rowController.search
)
.patch(

View File

@ -14,7 +14,15 @@ const selfhost = require("./selfhost")
const app = new Koa()
// set up top level koa middleware
app.use(koaBody({ multipart: true }))
app.use(
koaBody({
multipart: true,
formLimit: "10mb",
jsonLimit: "10mb",
textLimit: "10mb",
enableTypes: ["json", "form", "text"],
})
)
app.use(
logger({

View File

@ -41,9 +41,7 @@
<div class="root" use:styleable={$component.styles}>
<div class="content">
{#if logo}
<div class="logo-container">
<img src={logo} alt="logo" />
</div>
<div class="logo-container"><img src={logo} alt="logo" /></div>
{/if}
{#if title}

View File

@ -28,8 +28,13 @@
let page = 0
$: fetchData(table, page)
$: searchable = [...(table.indexes || []), ...columns]
// omit empty strings
$: parsedSearch = Object.keys(search).reduce((acc, next) => search[next] === "" ? acc : { ...acc, [next]: search[next] }, {})
$: parsedSearch = Object.keys(search).reduce(
(acc, next) =>
search[next] === "" ? acc : { ...acc, [next]: search[next] },
{}
)
async function fetchData(table, page) {
if (!isEmpty(table)) {
@ -40,8 +45,8 @@
search: parsedSearch,
pagination: {
pageSize,
page
}
page,
},
})
}
loaded = true