예제 #1
0
        private async Task <IHttpActionResult> InternalSearch(LibraryIndexHelper.IndexKinds indexKind, int offset, int limit, string categoryId = null, string q = null)
        {
            if (limit > AzureSearchHelper.SearchResults_MaxLimit)
            {
                throw new ArgumentException(String.Format("Search results limit is {0}.", AzureSearchHelper.SearchResults_MaxLimit));
            }

            var isPersonal = indexKind == LibraryIndexHelper.IndexKinds.PersonalCollection;
            var userId     = this.GetUserId();
            // Find resources in Azure Search.
            var search      = new AzureSearchHelper(indexKind, isPersonal ? userId : 0);
            var resultsJson = await search.Search(offset, limit, categoryId, q);

            if (isPersonal || (userId == 0))
            {
                return(new RawStringResult(this, resultsJson, RawStringResult.TextMediaType.Json));
            }
            else
            {
                // Common collection for an authorized user. Augment the results with personal data from database.
                var results = JsonConvert.DeserializeObject <AzureSearchResults>(resultsJson);

                if (results.Value.Any())
                {
                    var resourcesXml = new XElement("Resources",
                                                    results.Value.Select(i => new XElement("R", new XAttribute("Id", i.Id)))
                                                    )
                                       .ToString(SaveOptions.DisableFormatting);

                    const string sql   = @"
select Id, IsPersonal, LanguageLevelRating, Comment 
from dbo.libGetUserResources (@UserId, @Resources);
";
                    var          views = await DapperHelper.QueryResilientlyAsync <ResourceDto>(sql, new { UserId = userId, Resources = resourcesXml });

                    // Copy personalization values from the items we got from the database to the resources we got from search.
                    var resourceDict = results.Value.ToDictionary(i => i.Id);
                    foreach (var v in views)
                    {
                        // We expect the Ids returned from the database correspond to the Ids provided as arguments in XML. Otherwise a horrible KeyNotFoundException will ruine everything.
                        var r = resourceDict[v.Id];
                        // We do not store the Viewed value explicitly in the database. IsPersonal is not nullable. So the mere presense of an IsPersonal in a record means the resource has been viewed.
                        r.IsPersonal          = v.IsPersonal;
                        r.LanguageLevelRating = v.LanguageLevelRating;
                        r.Comment             = v.Comment;
                        r.Viewed = true;
                    }
                }

                // Since we send original raw Azure Search results in the "Personal" case as is, we use here Ok<AzureSearchResults> as well to substitute names from attributes for member names, i.e. "@odata.count" and "value".
                return(Ok <AzureSearchResults>(results));
            }
        }
예제 #2
0
 public AzureSearchHelper(LibraryIndexHelper.IndexKinds indexKind, int userId = 0)
     : this(LibraryIndexHelper.GetIndexName(indexKind), userId)
 {
 }