From e7fd13d6087712252b8a2864e94b7652a923abe4 Mon Sep 17 00:00:00 2001 From: Lykin <137850705+tiny-craft@users.noreply.github.com> Date: Tue, 21 Nov 2023 17:06:26 +0800 Subject: [PATCH] feat: add full search for stream --- backend/services/browser_service.go | 27 +++--- .../content_value/ContentValueStream.vue | 89 ++++++++----------- 2 files changed, 53 insertions(+), 63 deletions(-) diff --git a/backend/services/browser_service.go b/backend/services/browser_service.go index b63cf04..9fea2c4 100644 --- a/backend/services/browser_service.go +++ b/backend/services/browser_service.go @@ -645,7 +645,7 @@ func (b *browserService) GetKeyDetail(param types.KeyDetailParam) (resp types.JS var reset bool var subErr error doFilter := matchPattern != "*" - if param.Full || matchPattern != "*" { + if param.Full || doFilter { // load all cursor, reset = 0, true loadVal, subErr = client.LRange(ctx, key, 0, -1).Result() @@ -902,7 +902,8 @@ func (b *browserService) GetKeyDetail(param types.KeyDetailParam) (resp types.JS var msgs []redis.XMessage var last string var reset bool - if param.Full { + doFilter := matchPattern != "*" + if param.Full || doFilter { // load all last, reset = "", true msgs, err = client.XRevRange(ctx, key, "+", "-").Result() @@ -931,15 +932,21 @@ func (b *browserService) GetKeyDetail(param types.KeyDetailParam) (resp types.JS } } setEntryXLast(last) - items := make([]types.StreamEntryItem, len(msgs)) - for i, msg := range msgs { - items[i].ID = msg.ID - items[i].Value = msg.Values - if vb, merr := json.Marshal(msg.Values); merr != nil { - items[i].DisplayValue = "{}" - } else { - items[i].DisplayValue, _, _ = strutil.ConvertTo(string(vb), types.DECODE_NONE, types.FORMAT_JSON) + items := make([]types.StreamEntryItem, 0, len(msgs)) + for _, msg := range msgs { + it := types.StreamEntryItem{ + ID: msg.ID, + Value: msg.Values, } + if vb, merr := json.Marshal(msg.Values); merr != nil { + it.DisplayValue = "{}" + } else { + it.DisplayValue, _, _ = strutil.ConvertTo(string(vb), types.DECODE_NONE, types.FORMAT_JSON) + } + if doFilter && !strings.Contains(it.DisplayValue, param.MatchPattern) { + continue + } + items = append(items, it) } if err != nil { return items, reset, false, err diff --git a/frontend/src/components/content_value/ContentValueStream.vue b/frontend/src/components/content_value/ContentValueStream.vue index a0571b1..31d89c8 100644 --- a/frontend/src/components/content_value/ContentValueStream.vue +++ b/frontend/src/components/content_value/ContentValueStream.vue @@ -3,17 +3,18 @@ import { computed, h, ref } from 'vue' import { useI18n } from 'vue-i18n' import ContentToolbar from './ContentToolbar.vue' import AddLink from '@/components/icons/AddLink.vue' -import { NButton, NCode, NIcon, NInput, useThemeVars } from 'naive-ui' +import { NButton, NCode, NIcon, useThemeVars } from 'naive-ui' import { types, types as redisTypes } from '@/consts/support_redis_type.js' import EditableTableColumn from '@/components/common/EditableTableColumn.vue' import useDialogStore from 'stores/dialog.js' -import { includes, isEmpty, keys, size, some, values } from 'lodash' +import { includes, isEmpty, size } from 'lodash' import bytes from 'bytes' import { decodeTypes, formatTypes } from '@/consts/value_view_type.js' import useBrowserStore from 'stores/browser.js' import LoadList from '@/components/icons/LoadList.vue' import LoadAll from '@/components/icons/LoadAll.vue' import IconButton from '@/components/common/IconButton.vue' +import ContentSearchInput from '@/components/content_value/ContentSearchInput.vue' const i18n = useI18n() const themeVars = useThemeVars() @@ -48,7 +49,7 @@ const props = defineProps({ loading: Boolean, }) -const emit = defineEmits(['loadmore', 'loadall', 'reload', 'rename', 'delete']) +const emit = defineEmits(['loadmore', 'loadall', 'reload', 'rename', 'delete', 'match']) /** * @@ -57,30 +58,17 @@ const emit = defineEmits(['loadmore', 'loadall', 'reload', 'rename', 'delete']) const keyName = computed(() => { return !isEmpty(props.keyCode) ? props.keyCode : props.keyPath }) - -const filterOption = [ - { - value: 1, - label: i18n.t('common.field'), - }, - { - value: 2, - label: i18n.t('common.value'), - }, -] const filterType = ref(1) const browserStore = useBrowserStore() const dialogStore = useDialogStore() const keyType = redisTypes.STREAM -const idFilterOption = ref(null) const idColumn = computed(() => ({ key: 'id', title: 'ID', align: 'center', titleAlign: 'center', resizable: true, - filterOptionValue: idFilterOption.value, })) const valueFilterOption = ref(null) @@ -93,13 +81,15 @@ const valueColumn = computed(() => ({ filterOptionValue: valueFilterOption.value, filter: (value, row) => { const v = value.toString() - if (filterType.value === 1) { - // filter key - return some(keys(row.v), (key) => includes(key, v)) - } else { - // filter value - return some(values(row.v), (val) => includes(val, v)) + if (row.dv) { + return includes(row.dv, v) } + for (const k in row.v) { + if (includes(k, v) || includes(row.v[k], v)) { + return true + } + } + return false }, // sorter: (row1, row2) => row1.value - row2.value, render: (row) => { @@ -148,34 +138,23 @@ const onAddRow = () => { dialogStore.openAddFieldsDialog(props.name, props.db, props.keyPath, props.keyCode, types.STREAM) } -const filterValue = ref('') const onFilterInput = (val) => { valueFilterOption.value = val } -const onChangeFilterType = (type) => { - onFilterInput(filterValue.value) -} - -const clearFilter = () => { - idFilterOption.value = null - valueFilterOption.value = null +const onMatchInput = (matchVal, filterVal) => { + valueFilterOption.value = filterVal + emit('match', matchVal) } const onUpdateFilter = (filters, sourceColumn) => { - switch (filterType.value) { - case filterOption[0].value: - idFilterOption.value = filters[sourceColumn.key] - break - case filterOption[1].value: - valueFilterOption.value = filters[sourceColumn.key] - break - } + valueFilterOption.value = filters[sourceColumn.key] } +const searchInputRef = ref(null) defineExpose({ reset: () => { - clearFilter() + searchInputRef.value?.reset() }, }) @@ -196,20 +175,24 @@ defineExpose({ @rename="emit('rename')" />