Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Tom Engan 430 posts 1173 karma points
    Sep 23, 2016 @ 12:58
    Tom Engan
    0

    Razor search in a multilingual site

    @using Examine.LuceneEngine.SearchCriteria
    @inherits Umbraco.Web.Macros.PartialViewMacroPage
    
    @{
        string searchTerm = Request.QueryString["keywords"];
        if (String.IsNullOrWhiteSpace(searchTerm))
        {
            searchTerm = "";
        }
        var searcher = ExamineManager.Instance;
        var searchCriteria = searcher.CreateSearchCriteria();
        var query = searchCriteria.GroupedOr(new[] { "nodeName", "siteTitle", "content" }, searchTerm).Compile();
        var searchResults = searcher.Search(query).Where(r => r["__IndexType"] == "content").ToList();
    }
    
    @if (searchResults.Any())
    {
        <div class="search-results-box">
            @foreach (var result in searchResults)
            {
                var node = Umbraco.TypedContent(result.Id);
                var pathIds = result["__Path"].Split(',');
                var path = Umbraco.TypedContent(pathIds).Where(p => p != null).Select(p=> new {p.Name}).ToList();
                <div>
                    <section class="results-box">
                        <h3>
                            <a href="@node.Url">@String.Join(" > ", path.Select(p => p.Name))</a>
                        </h3>
                        @if (result.Fields.ContainsKey("siteTitle"))
                        {
                            <p class="results-title"><strong>@result["siteTitle"]</strong></p>
                        }
                        @if (result.Fields.ContainsKey("bodyText"))
                        {
                            <p>@result["bodyText"].Truncate(250)</p>
                        }
                    </section>
                </div>
            }
        </div> 
    }
    else
    {
        <p>
            No result: 
                @if (!String.IsNullOrWhiteSpace(searchTerm))
                {
                    <text>'@searchTerm'</text>
                }
        </p>
    }
    

    I have now prepared the site for two language versions:

    listerfriluft.no < norwegian language

    en.listerfriluft.no < english language

    The code works, but searches are currently showing result from both language versions.

    How can I separate search so they appear in only one language at the time?

    I would assume that it is the line that must be changed to distinguish between the language versions / subdomains, but how?

    var searchResults = searcher.Search(query).Where(r => r["__IndexType"] == "content").ToList();
    
  • Veronica Burd 76 posts 201 karma points
    Sep 23, 2016 @ 15:28
    Veronica Burd
    0

    Hi Tom,

    In my case I created an index handler to add a space delimited copy of the path field to my External index. I named the new field pathSearch.

    When I want to limit a search to a specific subset of nodes I add a clause to the search criteria using the pathSearch field.

    var query = searchCriteria.GroupedOr(new[] { "nodeName", "siteTitle", "content" }, searchTerm)
        .And().Field("pathSearch", idOfRootNode.ToString());
    

    Syntax may be a bit off as I don't have my code in front of me.

    Just to clarify I'm not using this for different languages/hosts but if you have separate root nodes for each language this approach should work.

    HTH Ver

  • Tom Engan 430 posts 1173 karma points
    Sep 28, 2016 @ 15:15
    Tom Engan
    0

    So how du you create this index handler with name "pathSearch"?

  • Tom Engan 430 posts 1173 karma points
    Sep 26, 2016 @ 12:57
    Tom Engan
    0

    Thanks for your feedback. I have only used an example using Examine, and still trying to separate the two languages. Could you give me more details of what I need to set up / configure? Could it be an idea and use Dictionary to set up two languages - "no" and "en" (with the Dictionary name "language")?

  • Ismail Mayat 4511 posts 10091 karma points MVP 2x admin c-trib
    Sep 26, 2016 @ 13:18
    Ismail Mayat
    0

    Tom,

    Create different indexes for each language, in the examine config you can setup start node as well.

    Also the other advantage of this is you can setup different language specific analysers for different languages. So we had to do this recently for german so our config looks like:

     <IndexSet SetName="External_de-DE_IndexSet" 
            IndexParentId="17268" 
            IndexPath="~/App_Data/TEMP/ExamineIndexes/ExternalIndex_de-DE/">
    

    You will need to modify your search code slightly so depending on the language site you are in you use that searcher.

    I DO NOT recommend putting different language content in the same index.

    Regards

    Ismail

  • Tom Engan 430 posts 1173 karma points
    Sep 27, 2016 @ 10:51
    Tom Engan
    0

    I've made these in ExamineIndex.config, but I don't know how to use this (norwegian first, than english):

    Is IndexParentId the Id value of Content "Hjem" (norwegian) and "Home" (english)?

      <IndexSet SetName="External_NoIndexSet" IndexParentId="1084" IndexPath="~/App_Data/TEMP/ExamineIndexes/External_No/" />
      <IndexSet SetName="External_EnIndexSet" IndexParentId="6614" IndexPath="~/App_Data/TEMP/ExamineIndexes/External_En/" />
    

    And I could need some help to get modifying the up-to-date search code (code abowe, or is it old?) to my Umbraco 7.5 website, so it filter out only searching site for the related language.

  • Ismail Mayat 4511 posts 10091 karma points MVP 2x admin c-trib
    Sep 27, 2016 @ 11:36
    Ismail Mayat
    0

    Have you added root node IDs and created separate indexes for each site? If so then you can just get that language searcher. So if you have created NoSearcher then when you get that searcher in code it will only search content in No site.

    Regards

    Ismail

  • Ismail Mayat 4511 posts 10091 karma points MVP 2x admin c-trib
    Sep 27, 2016 @ 11:39
    Ismail Mayat
    0

    Tom,

    To get it you would do

    var searcher = ExamineManager.Instance.collections["someindexsearcherhere] something like that I'm on move ATM so cannot get to laptop have a look at examine docs.

    Also make you create the searcher in config.

  • Tom Engan 430 posts 1173 karma points
    Sep 27, 2016 @ 13:38
    Tom Engan
    0

    Sometning like this?

    var searcher = ExamineManager.Instance.SearchProviderCollection["External_NoIndexSet"];
    var searchCriteria = searcher.CreateSearchCriteria(UmbracoExamine.IndexTypes.Content);
    

    where External-no-IndexSet is set in ExamineIndex.config?

      <IndexSet SetName="External_NoIndexSet"
              IndexParentId="1084"
              IndexPath="~/App_Data/TEMP/ExamineIndexes/ExternalIndex_no/" />
    

    Still don't work, and what to do when english language (I realy need a complete multilingual search example for Umbraco 7.5)...

  • Ismail Mayat 4511 posts 10091 karma points MVP 2x admin c-trib
    Sep 28, 2016 @ 15:32
    Ismail Mayat
    1

    This taken straight from the docs:

    var externalSearcher = ExamineManager.Instance.SearchProviderCollection["ExternalSearcher"];
    

    In your examinesettings.config make sure you have entry for that searcher:

      <add name="ExternalSearcher" type="UmbracoExamine.UmbracoExamineSearcher, UmbracoExamine"/>
    

    You will also need to add for the other languages. Then in your template code you can do

    if(language="no"){  var externalSearcher = ExamineManager.Instance.SearchProviderCollection["NoExternalSearcher"];}
    

    if(language="en"){var externalSearcher = ExamineManager.Instance.SearchProviderCollection["ExternalSearcher"];}

    I just kind of made that code up you will need to figure out which language instance you are in. You could do that by getting the region set for the site using culture and hostnames.

    Regards

    Ismail

  • Tom Engan 430 posts 1173 karma points
    Sep 29, 2016 @ 10:35
    Tom Engan
    100

    Yes, this works even with Dictonary, the name of root node, or the id of root node.

    The contents of the different languages are separated in search.

    ExamineSettings.config (added)

    <Examine>
      <ExamineIndexProviders>
        <providers>
            <add name="External_NoIndexer" type="UmbracoExamine.UmbracoContentIndexer, UmbracoExamine"/>
            <add name="External_EnIndexer" type="UmbracoExamine.UmbracoContentIndexer, UmbracoExamine"/>
        </providers>
      </ExamineIndexProviders>
    
      <ExamineSearchProviders defaultProvider="ExternalSearcher">
        <providers>
          <add name="External_NoSearcher" type="UmbracoExamine.UmbracoExamineSearcher, UmbracoExamine" />
          <add name="External_EnSearcher" type="UmbracoExamine.UmbracoExamineSearcher, UmbracoExamine" />
        </providers>
      </ExamineSearchProviders>
    </Examine>
    

    ExamineIndex.config (added)

    <ExamineLuceneIndexSets>
      <IndexSet SetName="External_NoIndexSet" IndexParentId="1084" IndexPath="~/App_Data/TEMP/ExamineIndexes/External_No/" />
      <IndexSet SetName="External_EnIndexSet" IndexParentId="6614" IndexPath="~/App_Data/TEMP/ExamineIndexes/External_En/" />
    </ExamineLuceneIndexSets>
    

    SearchResult.cshtml

    @using Examine.LuceneEngine.SearchCriteria
    @inherits Umbraco.Web.Macros.PartialViewMacroPage
    @{
        string searchTerm = Request.QueryString["keywords"];
        if (String.IsNullOrWhiteSpace(searchTerm))
        {
            searchTerm = "";
        }
    
        @* Norwegian as default - no need to specify root id *@
        var searcher = ExamineManager.Instance.SearchProviderCollection["External_NoSearcher"];
    
        @* Id for norwegian homepage - referenced to IndexParentId="1084" in ExamineIndex.config *@
        @* if (Model.Content.AncestorOrSelf(1).Id == 1084) { searcher = ExamineManager.Instance.SearchProviderCollection["External_NoSearcher"]; }*@
    
        @* Id for english homepage - referenced to IndexParentId="6614" in ExamineIndex.config *@
        if (Model.Content.AncestorOrSelf(1).Id == 6614) { searcher = ExamineManager.Instance.SearchProviderCollection["External_EnSearcher"]; }
    
        var searchCriteria = searcher.CreateSearchCriteria(UmbracoExamine.IndexTypes.Content);
        var query = searchCriteria.GroupedOr(new[] { "nodeName", "siteTitle", "content" }, searchTerm).Compile();
        var searchResults = searcher.Search(query).Where(r => r["__IndexType"] == "content").ToList();
    }
    
    @if (searchResults.Any())
    {
        <div class="search-results-box">
            @foreach (var result in searchResults)
            {
                var node = Umbraco.TypedContent(result.Id);
                var pathIds = result["__Path"].Split(',');
                var path = Umbraco.TypedContent(pathIds).Where(p => p != null).Select(p => new { p.Name }).ToList();
    
                if (node != null)
                {
                <div>
                    <section class="results-box">
                        <h3>
                            <a href="@node.Url">@String.Join(" > ", path.Select(p => p.Name))</a>
                        </h3>
                        <!-- <a href="@node.Url" class="results-url">@node.Url</a> -->
                        @if (result.Fields.ContainsKey("siteTitle"))
                        {
                            <p class="results-title"><strong>@result["siteTitle"]</strong></p>
                        }
                        @if (result.Fields.ContainsKey("bodyText"))
                        {
                            <p>@result["bodyText"].Truncate(250)</p>
                        } 
                    </section>
                    <hr style="opacity: .4" />
                </div>
                }
            }
        </div> 
    }
    else
    {
        <p>
            No result 
                @if (!String.IsNullOrWhiteSpace(searchTerm))
                {
                    <text>'@searchTerm'</text>
                }
        </p>
    }
    
  • Ismail Mayat 4511 posts 10091 karma points MVP 2x admin c-trib
    Sep 29, 2016 @ 15:34
    Ismail Mayat
    0

    Tom,

    Glad you got it working. One thing the line:

    var searchResults = searcher.Search(query).Where(r => r["__IndexType"] == "content").ToList();
    

    You do not need that extra linq bit. One its already covered when you create the searcher by passing in IndexTypes.Content. Second it is in efficient you should when working with examine do further filtering using linq just use examine.

    Regards

    Ismail

  • Tom Engan 430 posts 1173 karma points
    Sep 30, 2016 @ 09:17
    Tom Engan
    0

    Thanks. Doesn't have much experience with Linq, and wondered how the codes work. When I changed the line to

    var searchresults = searcher.Search (query); 
    

    I got the same result, so this line is now used instead.

    =========================================

    Following up with continuing questions in a new thread:

    https://our.umbraco.org/forum/extending-umbraco-and-using-the-api//80408-multilingual-alternate-canonical-and-301-and-ip-redirect

Please Sign in or register to post replies

Write your reply to:

Draft