简体   繁体   中英

Highlight Search Results from Elasticsearch using Vue.js

I am attempting to build a search engine with an Elasticsearch backend and a Vue.js front end. It is primarily based upon this tutorial . It was suggested that a nice feature would be to highlight search results with the initial search term ie if I search "foo" in the search bar, then a search result would look something like foo bar.

I have tried placing the v-html block into various divs, but usually to no success.

My elastic index records that match this format:

result._source.Title,
result._source.description, 
result._source.contact, 
result._source.contactEmail

HTML:

 <div class="row">
    <div class="col-md-6" v-for="result in results" v-html="highlight(result._source.Title)">
        <div class="ul">
            <ul>
                <li>{{ result._source.Title }},</li>
                <li>{{ result._source.description  }},</li>
                <li>{{ result._source.contact }},</li>
                <li>{{ result._source.contactEmail }} </li>

JS: highlight function

        highlight(text) {
            return text.replace(new RegExp(this.query, 'gi'), '<span class="highlight">$&</span>')
        }
}

I have been able to implement basic functionality to highlight a single data point, but the rest of the page does not render. For instance, in this example, title will be highlighted, but the description, contact, and contactEmail will not render on the page. Additionally, if the search term does not match the title, the page errors out.

It's likely due to to the function call in your v-html directive: highlight(result._source.Title) .

Instead you should be using v-html to bind to each result property, which allows you to replace occurrences in any of the properties before updating the template.

Try updating your code similar to the following:

 new Vue({ el: '#app', data() { return { content: [{ title: 'Result 1', text: `Phasellus euismod neque diam, aliquam commodo neque venenatis in. Sed non eros lorem. Fusce sit amet gravida nunc. Nunc non pulvinar tellus. Donec rutrum sagittis nulla eu commodo. Morbi condimentum molestie tortor venenatis dignissim. Aenean ac ligula at lectus pharetra sagittis. Integer convallis ipsum ex, ut congue urna auctor in. Sed consequat elit ipsum, eu vestibulum nisl egestas sit amet. Aenean eu mi et metus congue porttitor ut vitae augue. Donec congue semper euismod. Nam eget turpis eros. In vitae viverra eros.` }, { title: 'Result 2', text: `Nunc vehicula lorem a enim pharetra pellentesque. Nullam nulla nisi, imperdiet at blandit in, molestie sed ipsum. Curabitur elit nisl, aliquam vel urna at, tincidunt interdum tortor. Sed lacinia urna non tellus consectetur molestie. Cras nunc justo, suscipit eu luctus eget, viverra at nisl. Curabitur ut sodales justo, sit amet varius arcu. Nulla non varius justo, ut mattis diam. Nam venenatis malesuada enim. Ut id convallis augue. Pellentesque pretium aliquam porttitor. Donec at velit pulvinar, consequat eros at, ultrices urna. Sed non nisl tellus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nullam dictum ipsum dolor, vitae volutpat dolor porta non.` }, { title: 'Result 3', text: `Morbi bibendum justo enim, aliquam placerat magna euismod in. Sed ullamcorper augue ac nisl efficitur, eget ullamcorper neque rhoncus. Duis ac tristique orci. Curabitur lorem purus, varius eu sodales non, feugiat auctor orci. Pellentesque feugiat, felis eu accumsan ornare, lacus metus ultrices ipsum, vitae consequat velit neque in sapien. Nunc fringilla sollicitudin hendrerit. Vestibulum at massa convallis, finibus lacus ac, venenatis nulla. Nulla in condimentum metus. Donec sagittis nulla sed elit semper tristique. Vivamus facilisis sed lectus sed semper.` }, { title: 'Result 4', text: `Phasellus suscipit eros ex, sed auctor turpis accumsan non. In ultrices convallis sem id tempor. Sed elementum ac lectus et scelerisque. Mauris vel leo a sem elementum volutpat. Vestibulum congue urna id velit porta, id scelerisque nulla pulvinar. Aliquam sit amet iaculis enim. Vestibulum enim tortor, sodales ut pharetra semper, eleifend sed lectus. Phasellus fringilla leo vel turpis feugiat lacinia. Morbi neque dui, vulputate eget molestie non, hendrerit eu felis. Phasellus erat erat, tempus ut mi ut, maximus dapibus nulla. Phasellus dignissim sollicitudin velit sit amet rhoncus. Curabitur commodo magna eget ex consequat, eget sollicitudin metus rhoncus. Aenean enim libero, dictum nec tempus quis, molestie at nulla.` }, { title: 'Result 5', text: `Mauris ullamcorper mauris nec justo sodales, ac facilisis ipsum fringilla. Nam at urna eu ante luctus dignissim. In sit amet magna aliquam nibh tincidunt luctus vitae at arcu. Proin eu cursus tortor. Proin porttitor erat ac tortor ullamcorper lacinia. Curabitur sit amet ullamcorper ligula, rhoncus euismod est. Praesent non quam fermentum, bibendum lectus vel, auctor enim. Fusce eu viverra lectus. In molestie sit amet velit bibendum accumsan. Donec venenatis, urna sed convallis gravida, est est luctus mi, quis maximus ipsum metus sit amet ex. Vestibulum et nisi eu enim faucibus fermentum. Pellentesque pellentesque ultrices risus vel rutrum. Curabitur hendrerit urna in leo finibus rutrum. Maecenas posuere ultricies lectus eget elementum. Sed lacinia efficitur nisl, ac gravida urna ullamcorper consectetur. Aliquam erat volutpat.` } ], search: null } }, computed: { blocks() { if (this.search) { const regex = new RegExp(this.search, 'g') return this.content.map(c => { return { title: c.title.replace(regex, `<span class="highlight">${this.search}</span>`), text: c.text.replace(regex, `<span class="highlight">${this.search}</span>`) } }) } return this.content } } })
 .highlight { background-color: yellow; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> <input type="text" v-model="search"> <ul> <li v-for="(block,i) in blocks" :key="i"> <p>Title: <span v-html="block.title"></span></p> <p>Text: <span v-html="block.text"></span></p> </li> </ul> </div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM