पूर्ण पाठ ढूंढने (Pt | 3 |- | OpenSearch के साथ ASP (हिन्दी (Hindi))

पूर्ण पाठ ढूंढने (Pt | 3 |- | OpenSearch के साथ ASP

Saturday, 24 August 2024

//

9 minute read

परिचय

इस श्रृंखला के पिछले भागों में हमने पूर्ण पाठ खोज की संकल्पना और यह कैसे एक डाटाबेस के भीतर पाठ के लिए ढूंढने के लिए उपयोग किया जा सकता है का परिचय दिया।

पिछले हिस्से:

इस भाग में हम आप के नए चमकदार ओपन सर्च इंस्टैंसेस का उपयोग आरंभ करने के लिए कैसे कवर करेंगे ASP

सेटअप

एक बार जब हम OpenSearch इंस्टैंस अप और चल रहा है तो हम इसके साथ संवाद शुरू कर सकते हैं ओपन सर्च क्लाइंट के लिए पहले हम अपने सेटअप एक्सटेंशन में क्लाइंट सेटअप करें

    var openSearchConfig = services.ConfigurePOCO<OpenSearchConfig>(configuration.GetSection(OpenSearchConfig.Section));
        var config = new ConnectionSettings(new Uri(openSearchConfig.Endpoint))
            .EnableHttpCompression()
            .EnableDebugMode()
            .ServerCertificateValidationCallback((sender, certificate, chain, errors) => true)
            .BasicAuthentication(openSearchConfig.Username, openSearchConfig.Password);
        services.AddSingleton<OpenSearchClient>(c => new OpenSearchClient(config));

यह अंतिम बिन्दु और प्रमाणपत्र के साथ क्लाइंट को सेटअप करता है।

सूचकांकन डाटा

ओपन सर्च में मुख्य संकल्पना अनुक्रमणिका है

यह करने के लिए हम' उपयोग करेंगे ओपन सर्च क्लाइंट के लिए You can install this via NuGet

आप वहाँ पर ध्यान देंगे।

अब जब हम इसे स्थापित किया है तो हम सूचकांकन डेटा को देखना शुरू कर सकते हैं

एक अनुक्रमणिका बनाने का आधा है नीचे के कोड में आप देख सकते हैं कि हम 'मैप'अपनी अनुक्रमणिका मॉडल को दिखा सकते है। इस मॉडल के प्रत्येक क्षेत्र के लिए हम उस प्रकार को परिभाषित करते हैं जो यह है (पाठ, दिनांकM SK2 शब्दकुञ्जी आदि

प्रकार महत्वपूर्ण है क्योंकि यह परिभाषित करता है कि डेटा कैसे भंडारित किया जाता है और कैसे खोजा जा सकता है।

यहाँ भी वर्ग वास्तव में एक स्ट्रिंग है[लेकिन शब्दकुञ्जी प्रकार उन्हें सही तरीके से संभालने के लिए समझता है

   public async Task CreateIndex(string language)
    {
        var languageName = language.ConvertCodeToLanguageName();
        var indexName = GetBlogIndexName(language);

      var response =  await client.Indices.CreateAsync(indexName, c => c
            .Settings(s => s
                .NumberOfShards(1)
                .NumberOfReplicas(1)
            )
            .Map<BlogIndexModel>(m => m
                .Properties(p => p
                    .Text(t => t
                        .Name(n => n.Title)
                        .Analyzer(languageName)
                    )
                    .Text(t => t
                        .Name(n => n.Content)
                        .Analyzer(languageName)
                    )
                    .Text(t => t
                        .Name(n => n.Language)
                    )
                    .Date(t => t
                        .Name(n => n.LastUpdated)
                    )
                    .Date(t => t
                        .Name(n => n.Published)
                    )
                    .Date(t => t
                        .Name(n => n.LastUpdated)
                    )
                    .Keyword(t => t
                        .Name(n => n.Id)
                    )
                    .Keyword(t=>t
                        .Name(n=>n.Slug)
                    )
                    .Keyword(t=>t
                        .Name(n=>n.Hash)
                    )
                    .Keyword(t => t
                        .Name(n => n.Categories)
                    )
                )
            )
        );
        
        if (!response.IsValid)
        {
           logger.LogError("Failed to create index {IndexName}: {Error}", indexName, response.DebugInformation);
        }
    }

अनुक्रमणिका में आइटम जोड़ें

एक बार जब हम अपने अनुक्रमणिका सेटअप करने के लिए आइटमों को इसमें जोड़ने की जरूरत है, तो हमें इस अनुक्रमा में आइटम्स जोड़ना होगा।

आप देख सकते हैं कि हम शुरू में एक विधि called में बुलाते हैGetExistingPosts जो पहले से ही अनुक्रमणिका में मौजूद सभी पोस्टों को लौटाता है हम Hash और आईडी का उपयोग करते हैं पता लगाने के लिए अगर एक पोस्ट पहले से ही अनुक्रमणिका में है

    public async Task AddPostsToIndex(IEnumerable<BlogIndexModel> posts)
    {
        var existingPosts = await GetExistingPosts();
        var langPosts = posts.GroupBy(p => p.Language);
        langPosts=langPosts.Where(p => p.Key!="uk");
        langPosts = langPosts.Where(p =>
            p.Any(post => !existingPosts.Any(existing => existing.Id == post.Id && existing.Hash == post.Hash)));
        
        foreach (var blogIndexModels in langPosts)
        {
            
            var language = blogIndexModels.Key;
            var indexName = GetBlogIndexName(language);
            if(!await IndexExists(language))
            {
                await CreateIndex(language);
            }
            
            var bulkRequest = new BulkRequest(indexName)
            {
                Operations = new BulkOperationsCollection<IBulkOperation>(blogIndexModels.ToList()
                    .Select(p => new BulkIndexOperation<BlogIndexModel>(p))
                    .ToList()),
                Refresh = Refresh.True,
                ErrorTrace = true,
                RequestConfiguration = new RequestConfiguration
                {
                    MaxRetries = 3
                }
            };

            var bulkResponse = await client.BulkAsync(bulkRequest);
            if (!bulkResponse.IsValid)
            {
                logger.LogError("Failed to add posts to index {IndexName}: {Error}", indexName, bulkResponse.DebugInformation);
            }
            
        }
    }

एक बार जब हम मौजूदा पोस्टों और हमारे अनुपस्थित विश्लेषक को फिल्टर किया है, हम एक नया अनुक्रमणिका बनाते हैं।") और फिर एक बल्क निवेदन बनाने के लिए यह बल्क अनुरोध अनुक्रमणिका पर निष्पादित करने की प्रक्रियाओं का संग्रह है यह प्रत्येक वस्तु को एक से एक जोड़ने के बजाय अधिक प्रभावी है

आप' यह देखेंगे कि में BulkRequest हम सेट Refresh संपत्ति को true. इसका अर्थ है कि बल्क इंस्टीट्यूट पूरा होने के बाद सूचकांक ताज़ा किया जाता है।

अनुक्रमणिका खोज रहा है

यह देखने के लिए एक अच्छा तरीका है कि पता लगाएं क्या वास्तव में यहाँ बनाया गया है OpenSearch Dashboards पर Dev उपकरणों में जाएँ और एक खोज क्वेरी चलाएँ

GET /mostlylucid-blog-*
{}

यह क्वेरी हमें सभी अनुक्रमणिका पैटर्न मिलते हैं लौटाएगा mostlylucid-blog-*. (अभी आज तक हमारे सभी सूचकांक

{
  "mostlylucid-blog-ar": {
    "aliases": {},
    "mappings": {
      "properties": {
        "categories": {
          "type": "keyword"
        },
        "content": {
          "type": "text",
          "analyzer": "arabic"
        },
        "hash": {
          "type": "keyword"
        },
        "id": {
          "type": "keyword"
        },
        "language": {
          "type": "text"
        },
        "lastUpdated": {
          "type": "date"
        },
        "published": {
          "type": "date"
        },
        "slug": {
          "type": "keyword"
        },
        "title": {
          "type": "text",
          "analyzer": "arabic"
        }
      }
    },
    "settings": {
      "index": {
        "replication": {
          "type": "DOCUMENT"
..MANY MORE

ओपन सर्च डैशबोर्ड में डेव उपकरण आपके क्वेरी को अपने कोड में डालने से पहले परीक्षण करने का एक अच्छा तरीका है

विकास औज़ार

अनुक्रमणिका खोज रहा है

अब हम अनुक्रमणिका खोज शुरू कर सकते हैं Search यह करने के लिए क्लाइंट पर विधि यह है जहां OpenSearch की वास्तविक शक्ति में आता है . यह अक्षरशः विभिन्न प्रकार के प्रश्नों की दर्जनों आप अपने डेटा ढूंढने के लिए उपयोग कर सकते हैं. एक साधारण शब्दकुञ्जी खोज से लेकर एक जटिल खोज तक

    public async Task<List<BlogIndexModel>> GetSearchResults(string language, string query, int page = 1, int pageSize = 10)
    {
        var indexName = GetBlogIndexName(language);
        var searchResponse = await client.SearchAsync<BlogIndexModel>(s => s
                .Index(indexName)  // Match index pattern
                .Query(q => q
                    .Bool(b => b
                        .Must(m => m
                            .MultiMatch(mm => mm
                                .Query(query)
                                .Fields(f => f
                                    .Field(p => p.Title, boost: 2.0) 
                                    .Field(p => p.Categories, boost: 1.5) 
                                    .Field(p => p.Content)
                                )
                                .Type(TextQueryType.BestFields)
                                .Fuzziness(Fuzziness.Auto)
                            )
                        )
                    )
                )
                .Skip((page -1) * pageSize)  // Skip the first n results (adjust as needed)
                .Size(pageSize)  // Limit the number of results (adjust as needed)
        );

        if(!searchResponse.IsValid)
        {
            logger.LogError("Failed to search index {IndexName}: {Error}", indexName, searchResponse.DebugInformation);
            return new List<BlogIndexModel>();
        }
        return searchResponse.Documents.ToList();
    }

क्वेरी वर्णन

यह विधि GetSearchResultsएक विशेष ओपन सर्च अनुक्रमणिका को खोजने के लिए डिजाइन किया गया है जो ब्लॉग पोस्टों को प्राप्त करता है language, query, और पृष्ठांकन पैरामीटर page और pageSizeयहाँ यह क्या करता है

  1. अनुक्रमणिका चयन:

    • यह अनुक्रमणिका नाम का उपयोग कर प्राप्त करता है GetBlogIndexName दिए गए भाषा पर आधारित विधि. अनुक्रमणिका भाषा के अनुसार गतिशील रूप से चयनित की जाती है
  2. खोज क्वेरी:

    • क्वेरी एक का उपयोग करता है Bool एक के साथ प्रश्न Must यह सुनिश्चित करने के लिए खंड कि परिणाम कुछ मानदंडों से मिलते हैं
    • अंदर Must खंड, a MultiMatch क्वेरी का उपयोग बहुविध क्षेत्रों में खोज के लिए किया जाता है (Title, Categories, और Content).
      • बूस्टिंग: Title क्षेत्र को एक प्रोत्साहन दिया जाता है 2.0, यह खोज में अधिक महत्वपूर्ण बनाता है Categories की वृद्धि करता है 1.5. इसका अर्थ है, दस्तावेज़ जहां खोज क्वेरी शीर्षक या श्रेणियों में दिखाई देता है उच्च दर्जा प्राप्त करेंगे
      • क्वेरी प्रकार: यह उपयोग करता है BestFields, जो क्वेरी के लिए सर्वोत्तम मिलान क्षेत्र ढूंढने का प्रयास करता है
      • अस्पष्टता: Fuzziness.Auto पैरामीटर approximate matches के लिए अनुमति देता है
  3. पृष्ठांकन:

    • Skip विधि पहले छोड़ती है n परिणाम पर निर्भर करता है पृष्ठ संख्या, के रूप में गणना (page - 1) * pageSizeपृष्ठित परिणामों के माध्यम से नेविगेट करने में मदद करता है
    • Size विधि निर्दिष्ट किए गए दस्तावेजों को लौटाए जाने की संख्या को सीमित करती है pageSize.
  4. त्रुटि प्रबंधन:

    • यदि क्वेरी असफल है, एक त्रुटि लॉग की जाती है और एक खाली सूची लौटाया जाता है
  5. परिणाम:

    • विधि का एक सूची लौटाता है BlogIndexModel ढूंढें criteria के अनुरूप दस्तावेज़

तो आप देख सकते हैं कि हम अपने डेटा की खोज के बारे में बहुत लचीला हो सकता है

एक बड़ी सुविधा यह है कि हम कई भाषाओं को समर्थन कर सकते हैं।

नया खोज API

इस श्रृंखला के पिछले भागों में देखा गया खोज API के विपरीत, हम OpenSearch का उपयोग करके खोज प्रक्रिया को व्यापक रूप से सरल कर सकते हैं

   [HttpGet]
    [Route("osearch/{query}")]
   [ValidateAntiForgeryToken]
    public async Task<JsonHttpResult<List<SearchResults>>> OpenSearch(string query, string language = MarkdownBaseService.EnglishLanguage)
    {
        var results = await indexService.GetSearchResults(language, query);
        
        var host = Request.Host.Value;
        var output = results.Select(x => new SearchResults(x.Title.Trim(), x.Slug, @Url.ActionLink("Show", "Blog", new{ x.Slug}, protocol:"https", host:host) )).ToList();
        return TypedResults.Json(output);
    }

जैसा कि आप देख सकते हैं, हम परिणाम लौटाने के लिए अनुक्रमणिका में सभी डाटा की जरूरत है।

अंत में

इस पोस्ट में हमने देखा कि हम अपने ओपन सर्च इंस्टैंस के साथ बातचीत करने के लिए एक C# क्लाइंट लिखने का तरीका है

Finding related posts...
logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.