2016-04-30 11 views
2

Ich habe mehrere Attribute, die als attributesToRetrieve festgelegt sind. In meiner Vorlage werden jedoch nur einige davon angezeigt. Etwa so etwas wie dieses:Attribut nur in Suchergebnisvorlage anzeigen, wenn hervorgehobene Übereinstimmungen enthalten sind

<div id="results"> 
    <div>{{_highlightResult.attr1.value}}</div> 
    <div>{{_highlightResult.attr2.value}}</div> 
    <div>{{_highlightResult.attr3.value}}</div> 
</div> 

Auf diese Weise werden die Attribute in jedem Fall wiedergegeben werden, und hervorgehoben, wenn sie ein passendes Wort enthalten.

Nun würde Ich mag einen anderen Abschnitt erhöhen, wenn alle anderen Attribute nur dann angezeigt werden kann, aber wenn sie ein angepaßtes Wort hervorgehoben werden, so etwas wie enthalten:

<div id="results"> 
    <div>{{_highlightResult.attr_1.value}}</div> 
    <div>{{_highlightResult.attr_2.value}}</div> 
    <div>{{_highlightResult.attr_3.value}}</div> 
<!-- 
The following div will be rendered and displayed only 
if any of these special attributes contain an highlighted word. 
Only an attribute containing a matched word will be displayed 
--> 
    <div class="other-attr"> 
    {{_highlightResult.Long_SpecialAttr_1.value}} 
    {{_highlightResult.SpecialAttr_2.value}} 
    {{_highlightResult.SpecialAttr_3.value}} 
    </div> 
</div> 

Wie im Kommentar erwähnt, Dieser Abschnitt wird nur gerendert und angezeigt, wenn eines dieser speziellen Attribute ein hervorgehobenes Wort enthält. Außerdem wird nur ein Attribut angezeigt, das ein übereinstimmendes Wort enthält.

Plus, wie Sie sehen können, gibt es eine Long_SpecialAttr_1, es ist ein langes Textattribut, das ich möchte, dass es als ein Attribut mit Auszügen angezeigt wird.

Um eine bessere Vorstellung (vielleicht) zu geben, was ich versuche für diesen zusätzlichen Abschnitt ist unter jedem Suchergebnisse so etwas wie die eine Google-Anzeige zu erreichen, eine Art Text Blob Text mit drei Punkten auf die markierten Wörter enthalten diese Attribute.

Ist das möglich? Ich benutze Algolia instasearch.js, danke!

UPDATE

Dank @Jerska für seine Antwort, leider ein kleines Stück Code funktioniert nicht in meinem Fall, und zwar:

['highlight', 'snippet'].forEach(function (type) { 
    data['_' + type + 'Result'].forEach(function (elt) { 
    elt.display = elt.matchLevel !== 'none'; 
    }); 
}); 

mir in der Konsole einen Fehler geben data._snippetResult.forEach() is undefined Angabe . Also ich, dass etwas mit dieser Änderung:

for(var el in d._snippetResult) 
{ 
    // create new property with bool value, true if not "none" 
    d._snippetResult[el].display = d._snippetResult[el].matchLevel !== 'none'; 
}; 

Antwort

4

Zunächst einmal nur die Einstellungen Ihres Index zu klären, bevor die Zukunft, Algolia hebt auch die Attribute in attributesToSnippet.
Um die Attribute, die Sie ausschneiden, mit Auslassungspunkten zu versehen, können Sie snippetEllipsisText festlegen.
So können Sie diese Einstellungen in Ihrem Index verwenden mögen:

attributesToHighlight: ['attr_1', 'attr_2', 'attr_3', 'SpecialAttr_2', 'SpecialAttr_3'], 
attributesToSnippet: ['Long_SpecialAttr_1:3'], // Snippet should contain max 3 words 
snippetEllipsisText: '…' // This is the utf-8 "Horizontal ellipsis" character 

Auf der Front-End-Seite, in instantsearch.js Sie die transformData Parameter auf fast jeden Widget zugreifen zu können, verwenden können, und/oder ändern Sie die an die Vorlage übergebenen Daten.

In diesem speziellen Beispiel möchten wir uns transformData.item on the hits widget ansehen.

Der erste Schritt, um die Daten wäre zu protokollieren:

search.addWidget(
    instantsearch.widgets.hits({ 
    transformData: { 
     item: function (data) { 
     console.log(data); 
     return data; 
     } 
    } 
    }) 
); 

Dies ermöglicht es Ihnen, diese Art von Antwort zu sehen:

_highlightResult: { 
    attr_1: { 
    value: 'lorem <em>ipsum</em> dolor <em>sit</em>', 
    matchLevel: 'full', 
    matchedWords: ['ipsum', 'sit'] 
    }, 
    attr_2: { 
    value: 'lorem <em>ipsum</em> dolor', 
    matchLevel: 'partial', 
    matchedWords: ['ipsum'] 
    }, 
    attr_3: { 
    value: 'lorem', 
    matchLevel: 'none', 
    matchedWords: [] 
    }, 
    // ... 
}, 
_snippetResult: { 
    Long_SpecialAttr_1: { 
    value: 'lorem <em>ipsum</em> dolor …', // Let's assume Long_SpecialAttr_1 was equal to 'lorem ipsum dolor sit' 
    matchLevel: 'full' 
    } 
} 
Leider hier

ist die API ein bisschen da als inkonsistent Sie können sehen, Attribute mit Auszügen haben nicht das Attribut matchedWords, das hervorgehobene Attribute haben. Sie können wählen, es in attributesToSnippet und attributesToHighlight zu setzen, wenn Sie wirklich die Info wollen.

Für Ihren Anwendungsfall benötigen wir jedoch nur matchLevel. Was wir wollen, ist, Elemente nur anzuzeigen, wenn matchLevel !== 'none'. Leider Hogan.js, die zugrunde liegende Vorlage-Engine von instantsearch.js lässt nicht viel Flexibilität zu, so dass Sie nicht einfach diesen Vergleich in Ihre Vorlage einfügen können.

transformData: { 
    item: function (data) { 
    ['highlight', 'snippet'].forEach(function (type) { 
     var group = data['_' + type + 'Result']; 
     for (var attr in group) { 
     if (!group.hasOwnProperty(attr)) continue; 
     var elt = group[attr]; 
     elt.display = elt.matchLevel !== 'none'; 
     }; 
    }); 
    data.displaySpecial = false || 
     data._snippetResult.Long_SpecialAttr_1.display || 
     data._highlightResult.SpecialAttr_2.display || 
     data._highlightResult.SpecialAttr_3.display; 
    return data; 
    } 
} 

Und dann verwenden Sie diese neue Attribute in Ihrer Vorlage:

könnte eine Lösung, diese Bedingungen im Inneren des transformData vorauszuberechnen sein

<div id="results"> 
    <div>{{{_highlightResult.attr_1.value}}}</div> 
    <div>{{{_highlightResult.attr_2.value}}}</div> 
    <div>{{{_highlightResult.attr_3.value}}}</div> 
<!-- 
The following div will be rendered and displayed only 
if any of these special attributes contain an highlighted word. 
Only an attribute containing a matched word will be displayed 
--> 
    {{#displaySpecial}} 
    <div class="other-attr"> 
     {{#_snippetResult.Long_SpecialAttr_1.display}} 
     {{{_highlightResult.Long_SpecialAttr_1.value}}} 
     {{/_snippetResult.Long_SpecialAttr_1.display}} 

     {{#_highlightResult.SpecialAttr_2.display}} 
     {{{_highlightResult.SpecialAttr_2.value}}} 
     {{/_highlightResult.SpecialAttr_2.display}} 

     {{#_highlightResult.SpecialAttr_3.display}} 
     {{{_highlightResult.SpecialAttr_3.value}}} 
     {{/_highlightResult.SpecialAttr_3.display}} 
    </div> 
    {{#displaySpecial}} 
</div> 

(By the way, HTML zu rendern, können Sie sollte {{{ ... }}} anstelle von {{...}} verwenden, habe ich sie hier ersetzt) ​​

+1

Brilliant! Vielen Dank für diese sehr detaillierte Antwort! :) Ich hatte ein kleines Problem mit 'forEach', der Konsolenfehler meldete, dass es eine undefinierte Funktion gab (ich vermute, weil man' forEach' nur auf Arrays werfen kann, oder habe ich etwas übersehen?), Also habe ich dieses Bit modifiziert wie im Update erwähnt. – Gruber

+0

Oh ja, ich nahm meine Träume wahr. ES5 'forEach' funktioniert tatsächlich nicht mit Objekten, während die' forEach' Funktion von Unterstreichung/lodash funktioniert. Ich werde meine Antwort aktualisieren. – Jerska

+0

Ich sehe, aber ich denke, der hier wirklich fehlt könnte ich Lodash nicht verwenden, noch: P – Gruber