Replaced plain_text with search_text, a list of blocks with keys, and wired search UI to link to document key, allowing for linking to a search result's place in the text.
This commit is contained in:
parent
3c5b93b3c2
commit
1d862cd30f
|
@ -19,7 +19,7 @@ def es_document_list(doc_type):
|
|||
search = es.search(
|
||||
index='joyce',
|
||||
doc_type=doc_type,
|
||||
_source_exclude=['html_source', 'plain_text'],
|
||||
_source_exclude=['html_source', 'search_text'],
|
||||
body={
|
||||
'from': 0, 'size': 10000,
|
||||
'query': {'match_all': {}},
|
||||
|
@ -93,32 +93,60 @@ def group_search_results(es_results):
|
|||
for result in es_results:
|
||||
types.add(result['_type'])
|
||||
for type in types:
|
||||
list = []
|
||||
documents = []
|
||||
for result in es_results:
|
||||
if result['_type'] == type:
|
||||
entry = {'id': result['_id'], 'title': result['_source']['title'], 'highlight': result['highlight']['plain_text']}
|
||||
list.append(entry)
|
||||
output_results[type] = list
|
||||
hits = []
|
||||
for hit in result['inner_hits']['search_text']['hits']['hits']:
|
||||
hits.append(hit['_source'])
|
||||
entry = {
|
||||
'id': result['_id'],
|
||||
'title': result['_source']['title'],
|
||||
'hits': hits
|
||||
}
|
||||
if type == 'chapter':
|
||||
entry['number'] = result['_source']['number']
|
||||
documents.append(entry)
|
||||
output_results[type] = documents
|
||||
return output_results
|
||||
|
||||
def es_search_text(body):
|
||||
search = es.search(
|
||||
index='joyce',
|
||||
filter_path=['hits.hits._id', 'hits.hits._type', 'hits.hits._source.title', 'hits.hits._source.number', 'hits.hits.highlight', 'hits.hits.title'],
|
||||
filter_path=[
|
||||
'hits.hits._id',
|
||||
'hits.hits._type',
|
||||
'hits.hits._source.title',
|
||||
'hits.hits._source.number',
|
||||
'hits.hits.title',
|
||||
'hits.hits.inner_hits.search_text.hits.hits._source'
|
||||
],
|
||||
body={
|
||||
'from': 0,
|
||||
'size': 10,
|
||||
'query': {
|
||||
'match': {
|
||||
'plain_text': {
|
||||
'query': body
|
||||
"nested": {
|
||||
"path": "search_text",
|
||||
"query": {
|
||||
"bool": {
|
||||
"must": [
|
||||
{ "match": { "search_text.text": body}}
|
||||
]
|
||||
}
|
||||
},
|
||||
"inner_hits": {
|
||||
"highlight": {
|
||||
"fields": {
|
||||
"search_text.text": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'highlight' : {
|
||||
'number_of_fragments' : 15,
|
||||
'fields' : {
|
||||
'plain_text': {
|
||||
'search_text': {
|
||||
'matched_fields': 'text',
|
||||
'type': 'unified',
|
||||
'pre_tags' : [''],
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
8
setup.py
8
setup.py
|
@ -43,21 +43,21 @@ create_index_settings = {
|
|||
'number': {'type': 'integer'},
|
||||
'title': {'type': 'keyword'},
|
||||
'html_source': {'type': 'text', 'analyzer': 'html_analyzer'},
|
||||
'plain_text': {'type': 'text'}
|
||||
'search_text': {'type': 'nested'}
|
||||
}
|
||||
},
|
||||
'note': {
|
||||
'properties': {
|
||||
'title': {'type': 'keyword'},
|
||||
'html_source': {'type': 'text', 'analyzer': 'html_analyzer'},
|
||||
'plain_text': {'type': 'text'}
|
||||
'search_text': {'type': 'nested'}
|
||||
}
|
||||
},
|
||||
'note': {
|
||||
'tag': {
|
||||
'properties': {
|
||||
'title': {'type': 'keyword'},
|
||||
'html_source': {'type': 'text', 'analyzer': 'html_analyzer'},
|
||||
'plain_text': {'type': 'text'}
|
||||
'search_text': {'type': 'nested'}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,24 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
const SearchResultSnippet = ({snippet}) =>
|
||||
<div>
|
||||
{snippet}...
|
||||
const buildSnippetLink = (key, docType, route) => {
|
||||
console.log('DocType is ', docType)
|
||||
if (docType === 'chapter') {
|
||||
return '/' + route + '#' + key
|
||||
} else {
|
||||
return '/' + docType + 's/' + route + '#' + key
|
||||
}
|
||||
}
|
||||
|
||||
const SearchResultSnippet = ({snippet, docType, route}) =>
|
||||
<div id={snippet.key}>
|
||||
<a href={buildSnippetLink(snippet.key, docType, route)}>
|
||||
{snippet.text}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
SearchResultSnippet.propTypes = {
|
||||
snippet: PropTypes.string,
|
||||
snippet: PropTypes.object,
|
||||
}
|
||||
|
||||
export default SearchResultSnippet
|
|
@ -9,8 +9,8 @@ const SearchResultGroup = ({docType, docTitle, results}) =>
|
|||
{results.map(result =>
|
||||
<div key={result.id}>
|
||||
<h5>{result.title}</h5>
|
||||
{result.highlight.map(highlight =>
|
||||
<SearchResultSnippet snippet={highlight} />
|
||||
{result.hits.map(hit =>
|
||||
<SearchResultSnippet key={hit.key} snippet={hit} docType={docType} route={docType === 'chapter' ? result.number : result.id}/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
|
|
@ -4,7 +4,7 @@ import { stateToHTML } from 'draft-js-export-html'
|
|||
import actions from '../actions'
|
||||
import helpers from '../modules/helpers'
|
||||
|
||||
import { html_export_options, convertToPlainText } from '../modules/editorSettings.js'
|
||||
import { html_export_options, convertToSearchText } from '../modules/editorSettings.js'
|
||||
|
||||
const joyceInterface = store => next => action => {
|
||||
next(action)
|
||||
|
@ -14,7 +14,7 @@ const joyceInterface = store => next => action => {
|
|||
break
|
||||
case 'SUBMIT_DOCUMENT_EDIT':
|
||||
const textContent = action.editorState.getCurrentContent()
|
||||
const data = { title: action.documentTitleInput, html_source: stateToHTML(textContent, html_export_options), plain_text: convertToPlainText(textContent) }
|
||||
const data = { title: action.documentTitleInput, html_source: stateToHTML(textContent, html_export_options), search_text: convertToSearchText(textContent) }
|
||||
if (action.currentDocument.id) {
|
||||
data.id = action.currentDocument.id
|
||||
}
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
import { convertToRaw } from 'draft-js'
|
||||
|
||||
export const html_export_options = {
|
||||
blockStyleFn: (block) => {
|
||||
const key = block.getKey()
|
||||
return {
|
||||
attributes: {
|
||||
id: key
|
||||
}
|
||||
}
|
||||
},
|
||||
entityStyleFn: (entity) => {
|
||||
const entityType = entity.get('type').toUpperCase()
|
||||
if (entityType === 'LINK') {
|
||||
|
@ -8,7 +16,7 @@ export const html_export_options = {
|
|||
return {
|
||||
element: 'a',
|
||||
attributes: {
|
||||
'href': data.url,
|
||||
'href': data.url,
|
||||
'data-target': '#annotation_modal',
|
||||
'data-toggle': 'modal'
|
||||
}
|
||||
|
@ -17,10 +25,12 @@ export const html_export_options = {
|
|||
}
|
||||
}
|
||||
|
||||
export const convertToPlainText = contentState => {
|
||||
export const convertToSearchText = contentState => {
|
||||
const rawState = convertToRaw(contentState)
|
||||
return rawState.blocks.reduce(
|
||||
(plaintText, block) => plaintText + block.text + '\n',
|
||||
''
|
||||
)
|
||||
const searchText = rawState.blocks.reduce(
|
||||
(searchText, block) => ([...searchText, {key: block.key, text: block.text}]),
|
||||
[]
|
||||
)
|
||||
console.log('Search text result:', searchText)
|
||||
return searchText
|
||||
}
|
Loading…
Reference in New Issue