Пример #1
0
        public virtual SearchResult <SearchableBase> Search(SearchTextQuery query)
        {
            var searchRequest = GetSearchDescriptor()
                                .Query(q =>
                                       q.Bool(b => b
                                              .Should(GetQueryContainers(query.Text))
                                              .MinimumShouldMatch(MinimumShouldMatch.Fixed(MinimumShouldMatches))))
                                .PostFilter(pf => pf.Bool(b => b.Must(GetSearchPostFilters(query))));

            ApplyAggregations(searchRequest, query);

            _searchSorting.Apply(searchRequest, query);

            _searchPagingHelper.Apply(searchRequest, query);

            if (query.ApplyHighlights)
            {
                ApplyHighlight(searchRequest);
            }

            var queryResult  = _elasticSearchRepository.SearchByIndex(searchRequest);
            var searchResult = ParseResults(queryResult);

            return(searchResult);
        }
Пример #2
0
        /// <summary>
        /// Adds a filter for a list of names.
        /// </summary>
        /// <typeparam name="T">Entry name type</typeparam>
        /// <param name="query">Entry name query. Cannot be null.</param>
        /// <param name="textQuery">Name query filter. Cannot be null.</param>
        /// <returns>Filtered query. Cannot be null.</returns>
        public static IQueryable <T> AddEntryNameFilter <T>(IQueryable <T> query, SearchTextQuery textQuery)
            where T : LocalizedString
        {
            if (textQuery.IsEmpty)
            {
                return(query);
            }

            var nameFilter = textQuery.Query;

            switch (textQuery.MatchMode)
            {
            case NameMatchMode.Exact:
                return(query.Where(m => m.Value == nameFilter));

            case NameMatchMode.Partial:
                return(query.Where(m => m.Value.Contains(nameFilter)));

            case NameMatchMode.StartsWith:
                return(query.Where(m => m.Value.StartsWith(nameFilter)));

            case NameMatchMode.Words:
                var words = textQuery.Words;

                foreach (var word in words.Take(MaxSearchWords))
                {
                    var temp = word;
                    query = query.Where(q => q.Value.Contains(temp));
                }

                return(query);
            }

            return(query);
        }
Пример #3
0
        public LyricsForSongContract GetRandomLyricsForSong(string query)
        {
            return(HandleQuery(session =>
            {
                var songContract = Find(session, new SongQueryParams(SearchTextQuery.Create(query),
                                                                     new SongType[] { }, 0, 10, false,
                                                                     SongSortRule.Name, false, true, null)
                {
                    AdvancedFilters = new[] { new AdvancedSearchFilter {
                                                  FilterType = AdvancedFilterType.Lyrics, Param = AdvancedSearchFilter.Any
                                              } }
                }).Items;

                if (!songContract.Any())
                {
                    return null;
                }

                var songIds = songContract.Select(s => s.Id).ToArray();

                var songs = session.Query <Song>().Where(s => songIds.Contains(s.Id)).ToArray();
                var allLyrics = songs.SelectMany(s => s.Lyrics).ToArray();

                if (!allLyrics.Any())
                {
                    return null;
                }

                var lyrics = allLyrics[new Random().Next(allLyrics.Length)];

                return new LyricsForSongContract(lyrics);
            }));
        }
Пример #4
0
        private SearchTextQuery ProcessAdvancedSearch(SearchTextQuery textQuery, SongQueryParams queryParams)
        {
            if (textQuery.IsEmpty || textQuery.MatchMode == NameMatchMode.Exact || textQuery.MatchMode == NameMatchMode.StartsWith || !textQuery.OriginalQuery.StartsWith("!"))
            {
                return(textQuery);
            }

            var parsed = SearchParser.ParseQuery(textQuery.OriginalQuery.Substring(1));

            var artistNames = parsed.GetValues("artist").ToArray();

            if (artistNames.Any())
            {
                queryParams.ArtistNames = artistNames;
            }

            var words = parsed.GetValues("").ToArray();

            if (words.Any())
            {
                queryParams.Common.TextQuery = new SearchTextQuery(textQuery.Query, NameMatchMode.Words, textQuery.OriginalQuery, words);
                return(queryParams.Common.TextQuery);
            }
            else
            {
                return(textQuery);
            }
        }
Пример #5
0
        private IQueryable <Album> CreateQuery(
            AlbumQueryParams queryParams,
            ParsedAlbumQuery parsedQuery,
            NameMatchMode?nameMatchMode = null)
        {
            var artistIds = EntryIdsCollection.CreateWithFallback(queryParams.ArtistParticipation.ArtistIds.Ids, parsedQuery.ArtistId);
            var textQuery = SearchTextQuery.Create(parsedQuery.Name, nameMatchMode ?? queryParams.Common.NameMatchMode);

            var query = Query <Album>()
                        .WhereIsDeleted(queryParams.Deleted)
                        .WhereHasName(textQuery, allowCatNum: true)
                        .WhereStatusIs(queryParams.Common.EntryStatus)
                        .WhereHasArtistParticipationStatus(queryParams.ArtistParticipation, artistIds, querySource.OfType <Artist>())
                        .WhereHasBarcode(queryParams.Barcode)
                        .WhereHasType(queryParams.AlbumType)
                        .WhereHasTags(queryParams.TagIds, queryParams.ChildTags)
                        .WhereHasTags(queryParams.Tags)
                        .WhereHasTag(parsedQuery.TagName)
                        .WhereReleaseDateIsAfter(queryParams.ReleaseDateAfter)
                        .WhereReleaseDateIsBefore(queryParams.ReleaseDateBefore)
                        .WhereSortBy(queryParams.SortRule)
                        .WhereMatchFilters(queryParams.AdvancedFilters);

            return(query);
        }
Пример #6
0
        public void ParseTextQuery_Id()
        {
            var result = songSearch.ParseTextQuery(SearchTextQuery.Create("id:3939"));

            Assert.IsFalse(result.HasNameQuery, "HasNameQuery");
            Assert.AreEqual(3939, result.Id, "Id query");
        }
Пример #7
0
        public ParsedSongQuery ParseTextQuery(SearchTextQuery textQuery)
        {
            var query = textQuery.OriginalQuery;

            if (string.IsNullOrWhiteSpace(query))
            {
                return(new ParsedSongQuery());
            }

            var trimmed = query.Trim();

            var term = GetTerm(trimmed, "id", "tag", "artist-tag", "artist-type", "publish-date");

            return((term?.PropertyName) switch
            {
                "tag" => new ParsedSongQuery {
                    TagName = term.Value
                },
                "artist-tag" => new ParsedSongQuery {
                    ArtistTag = term.Value
                },
                "artist-type" => new ParsedSongQuery {
                    ArtistType = EnumVal <ArtistType> .ParseSafe(term.Value, ArtistType.Unknown)
                },
                "id" => new ParsedSongQuery {
                    Id = PrimitiveParseHelper.ParseIntOrDefault(term.Value, 0)
                },
                "publish-date" => ParseDateRange(term.Value),
                _ => ParseReferenceQuery(trimmed, query) ?? new ParsedSongQuery {
                    Name = textQuery
                },
            });
Пример #8
0
        public void ParseTextQuery_Name()
        {
            var result = songSearch.ParseTextQuery(SearchTextQuery.Create("Hatsune Miku"));

            Assert.IsTrue(result.HasNameQuery, "HasNameQuery");
            Assert.AreEqual("Hatsune Miku", result.Name.Query, "Name query");
        }
Пример #9
0
        public void ParseTextQuery_DateRange()
        {
            var result = songSearch.ParseTextQuery(SearchTextQuery.Create("publish-date:2015/9/3-2015/10/1"));

            Assert.AreEqual(new DateTime(2015, 9, 3), result.PublishedAfter, "Publish date after");
            Assert.AreEqual(new DateTime(2015, 10, 1), result.PublishedBefore, "Publish date before");
        }
Пример #10
0
        public T FindFirst <T>(Func <Song, ISession, T> fac, string[] query, NameMatchMode nameMatchMode)
            where T : class
        {
            return(HandleQuery(session =>
            {
                foreach (var q in query.Where(q => !string.IsNullOrWhiteSpace(q)))
                {
                    var result = Find(session,
                                      new SongQueryParams
                    {
                        Common = new CommonSearchParams
                        {
                            TextQuery = SearchTextQuery.Create(q, nameMatchMode),
                            OnlyByName = true,
                            MoveExactToTop = true
                        },
                        LanguagePreference = LanguagePreference,
                        Paging = new PagingProperties(0, 30, false)
                    });

                    if (result.Items.Any())
                    {
                        return fac(result.Items.First(), session);
                    }
                }

                return null;
            }));
        }
Пример #11
0
        public PartialFindResult <SongInListForApiContract> GetSongs(int listId,
                                                                     string query     = "",
                                                                     string songTypes = null,
                                                                     [FromUri] PVServices?pvServices = null,
                                                                     [FromUri] int[] tagId           = null,
                                                                     [FromUri] int[] artistId        = null,
                                                                     bool childVoicebanks            = false,
                                                                     [FromUri] AdvancedSearchFilter[] advancedFilters = null,
                                                                     int start                      = 0, int maxResults = defaultMax, bool getTotalCount = false,
                                                                     SongSortRule?sort              = null,
                                                                     NameMatchMode nameMatchMode    = NameMatchMode.Auto,
                                                                     SongOptionalFields fields      = SongOptionalFields.None,
                                                                     ContentLanguagePreference lang = ContentLanguagePreference.Default
                                                                     )
        {
            maxResults = Math.Min(maxResults, absoluteMax);
            var types = EnumVal <SongType> .ParseMultiple(songTypes);

            return(queries.GetSongsInList(
                       new SongListQueryParams {
                TextQuery = SearchTextQuery.Create(query, nameMatchMode),
                ListId = listId,
                Paging = new PagingProperties(start, maxResults, getTotalCount),
                PVServices = pvServices,
                ArtistIds = artistId,
                ChildVoicebanks = childVoicebanks,
                TagIds = tagId,
                SortRule = sort,
                AdvancedFilters = advancedFilters,
                SongTypes = types
            },
                       songInList => new SongInListForApiContract(songInList, lang, fields)));
        }
Пример #12
0
        public PartialFindResult <UserForApiContract> GetList(
            string query                = "",
            UserGroupId groups          = UserGroupId.Nothing,
            DateTime?joinDateAfter      = null,
            DateTime?joinDateBefore     = null,
            NameMatchMode nameMatchMode = NameMatchMode.Auto,
            int start                 = 0,
            int maxResults            = 10,
            bool getTotalCount        = false,
            UserSortRule?sort         = null,
            bool includeDisabled      = false,
            bool onlyVerified         = false,
            string knowsLanguage      = null,
            UserOptionalFields fields = UserOptionalFields.None)
        {
            var queryParams = new UserQueryParams {
                Common              = new CommonSearchParams(SearchTextQuery.Create(query, nameMatchMode), false, false),
                Group               = groups,
                IncludeDisabled     = includeDisabled,
                OnlyVerifiedArtists = onlyVerified,
                KnowsLanguage       = knowsLanguage,
                JoinDateAfter       = joinDateAfter,
                JoinDateBefore      = joinDateBefore,
                Sort   = sort ?? UserSortRule.Name,
                Paging = new PagingProperties(start, maxResults, getTotalCount)
            };

            return(queries.GetUsers(queryParams, user => new UserForApiContract(user, userIconFactory, fields)));
        }
Пример #13
0
        public static ArtistSearchTextQuery Create(SearchTextQuery textQuery)
        {
            var canonizedName = ArtistHelper.GetCanonizedName(textQuery.Query);

            // Can't use the existing words collection here as they are noncanonized
            return(new ArtistSearchTextQuery(canonizedName, textQuery.MatchMode, textQuery.OriginalQuery));
        }
Пример #14
0
        public ActionResult Index(string filter = null, UserGroupId?groupId = null)
        {
            var vm = new Models.User.Index {
                Filter = filter, GroupId = groupId
            };

            if (!string.IsNullOrEmpty(filter))
            {
                var queryParams = new UserQueryParams
                {
                    Common = new CommonSearchParams(SearchTextQuery.Create(filter), false, false),
                    Paging = new PagingProperties(0, 1, true),
                    Group  = groupId ?? UserGroupId.Nothing
                };

                var result = Data.GetUsers(queryParams, u => u.Name);

                if (result.TotalCount == 1 && result.Items.Length == 1)
                {
                    return(RedirectToAction("Profile", new { id = result.Items[0] }));
                }
            }

            return(View(vm));
        }
Пример #15
0
        public FeedResult Feed(IndexRouteParams indexParams)
        {
            WebHelper.VerifyUserAgent(Request);

            var pageSize    = (indexParams.pageSize.HasValue ? Math.Min(indexParams.pageSize.Value, 30) : 30);
            var sortRule    = indexParams.sort ?? SongSortRule.Name;
            var timeFilter  = DateTimeUtils.ParseFromSimpleString(indexParams.since);
            var filter      = indexParams.filter;
            var songType    = indexParams.songType ?? SongType.Unspecified;
            var matchMode   = indexParams.matchMode ?? NameMatchMode.Auto;
            var onlyWithPVs = indexParams.onlyWithPVs ?? false;
            var minScore    = indexParams.minScore ?? 0;

            var textQuery   = SearchTextQuery.Create(filter, matchMode);
            var queryParams = new SongQueryParams(textQuery,
                                                  songType != SongType.Unspecified ? new[] { songType } : new SongType[] { },
                                                  0, pageSize, false, sortRule, false, false, null)
            {
                TimeFilter  = timeFilter,
                OnlyWithPVs = onlyWithPVs,
                ArtistIds   = !indexParams.artistId.HasValue || indexParams.artistId.Value == 0 ? null : new [] { indexParams.artistId.Value },
                MinScore    = minScore,
            };

            var result = Service.FindWithThumbPreferNotNico(queryParams);

            var fac  = new SongFeedFactory();
            var feed = fac.Create(result.Items,
                                  VocaUriBuilder.CreateAbsolute(Url.Action("Index", indexParams)),
                                  song => RenderPartialViewToString("SongItem", song),
                                  song => Url.Action("Details", new { id = song.Id }));

            return(new FeedResult(new Atom10FeedFormatter(feed)));
        }
Пример #16
0
        public string[] FindNames(SearchTextQuery textQuery, int maxResults)
        {
            if (textQuery.IsEmpty)
            {
                return new string[] {}
            }
            ;

            var artistTextQuery = ArtistSearchTextQuery.Create(textQuery);
            var tagTextQuery    = TagSearchTextQuery.Create(textQuery);

            return(HandleQuery(session => {
                var artistNames = session.Query <ArtistName>()
                                  .WhereArtistNameIs(artistTextQuery)
                                  .Where(a => !a.Artist.Deleted)
                                  .Select(n => n.Value)
                                  .OrderBy(n => n)
                                  .Distinct()
                                  .Take(maxResults)
                                  .ToArray();

                var albumNames = session.Query <AlbumName>()
                                 .WhereEntryNameIs(textQuery)
                                 .Where(a => !a.Album.Deleted)
                                 .Select(n => n.Value)
                                 .OrderBy(n => n)
                                 .Distinct()
                                 .Take(maxResults)
                                 .ToArray();

                var songNames = session.Query <SongName>()
                                .WhereEntryNameIs(textQuery)
                                .Where(a => !a.Song.Deleted)
                                .Select(n => n.Value)
                                .OrderBy(n => n)
                                .Distinct()
                                .Take(maxResults)
                                .ToArray();

                var tagNames = session.Query <TagName>()
                               .WhereEntryNameIs(tagTextQuery)
                               .Where(a => !a.Entry.Deleted)
                               .Select(t => t.Value)
                               .OrderBy(t => t)
                               .Take(maxResults)
                               .ToArray();

                var allNames = artistNames
                               .Concat(albumNames)
                               .Concat(songNames)
                               .Concat(tagNames)
                               .Distinct()
                               .OrderBy(n => n)
                               .Take(maxResults)
                               .ToArray();

                return NameHelper.MoveExactNamesToTop(allNames, textQuery.Query);
            }));
        }
Пример #17
0
        public void Find_NameQuotedExact()
        {
            queryParams.Common.TextQuery = SearchTextQuery.Create("\"Anger\"");

            var result = CallFind();

            AssertTags(result, "Anger");
        }
Пример #18
0
        public void Find_NameMatchModeExact()
        {
            queryParams.Common.TextQuery = SearchTextQuery.Create("Anger", NameMatchMode.Exact);

            var result = CallFind();

            AssertTags(result, "Anger");
        }
Пример #19
0
        public void Find_NameWords()
        {
            queryParams.Common.TextQuery = SearchTextQuery.Create("Anger");

            var result = CallFind();

            AssertTags(result, "Anger", "Anger [EXTEND RMX]");
        }
 public PartialFindResult <ReleaseEventSeriesContract> GetList(
     string query = "",
     int start    = 0, int maxResults = defaultMax, bool getTotalCount = false,
     NameMatchMode nameMatchMode = NameMatchMode.Auto)
 {
     return(queries.FindSeries(s => new ReleaseEventSeriesContract(s), SearchTextQuery.Create(query, nameMatchMode),
                               new PagingProperties(start, maxResults, getTotalCount)));
 }
Пример #21
0
        public PartialFindResult <AlbumContract> Find(
            SearchTextQuery textQuery, DiscType discType, int start, int maxResults, bool getTotalCount,
            AlbumSortRule sortRule = AlbumSortRule.Name, bool moveExactToTop = false)
        {
            var queryParams = new AlbumQueryParams(textQuery, discType, start, maxResults, getTotalCount, sortRule, moveExactToTop);

            return(Find(queryParams));
        }
Пример #22
0
 protected virtual QueryContainer[] GetSearchPostFilters(SearchTextQuery query)
 {
     return(new[]
     {
         GetSearchableTypeQueryContainers(query.SearchableTypeIds),
         GetOnlyPinnedQueryContainer(query.OnlyPinned)
     });
 }
Пример #23
0
        /// <summary>
        /// Filters query by one or more tag names.
        /// The tag has to match at least one of the names.
        /// For empty list of names (or null) nothing is matched.
        /// The name has to be exact match (case insensitive).
        /// </summary>
        /// <param name="query">Query to be filtered. Cannot be null.</param>
        /// <param name="names">List of names to filter by. Can be null or empty, but in that case no tags will be matched.</param>
        /// <returns>Filtered query. Cannot be null.</returns>
        public static IQueryable <Tag> WhereHasName(this IQueryable <Tag> query, params string[] names)
        {
            names = names ?? new string[0];

            var queries = names.Select(n => SearchTextQuery.Create(n, NameMatchMode.Exact));

            return(query.WhereHasNameGeneric <Tag, TagName>(queries));
        }
Пример #24
0
        public AlbumQueryParams(SearchTextQuery textQuery, DiscType discType, int start, int maxResults, bool getTotalCount,
                                AlbumSortRule sortRule = AlbumSortRule.Name, bool moveExactToTop = false)
        {
            Common = new CommonSearchParams(textQuery, false, moveExactToTop);
            Paging = new PagingProperties(start, maxResults, getTotalCount);

            AlbumType = discType;
            SortRule  = sortRule;
        }
Пример #25
0
        public PartialFindResult <SongWithAlbumAndPVsContract> FindSongs(string term, int maxResults, NameMatchMode nameMatchMode = NameMatchMode.Auto)
        {
            var sampleSize = Math.Min(maxResults * 2, 30);

            var results = songService.FindWithAlbum(new SongQueryParams(
                                                        SearchTextQuery.Create(term, nameMatchMode), new SongType[] {}, 0, sampleSize, true, SongSortRule.Name, false, true, null), false);

            return(new PartialFindResult <SongWithAlbumAndPVsContract>(results.Items.Take(maxResults).ToArray(), results.TotalCount, results.Term));
        }
Пример #26
0
        private ParsedArtistQuery ParseTextQuery(SearchTextQuery textQuery)
        {
            if (textQuery.IsEmpty)
            {
                return(new ParsedArtistQuery());
            }

            var trimmed = textQuery.OriginalQuery.Trim();

            var term = SearchWord.GetTerm(trimmed, "id");

            if (term == null)
            {
                var trimmedLc = trimmed.ToLowerInvariant();

                // Optimization: check prefix, in most cases the user won't be searching by URL
                if (trimmedLc.StartsWith("/ar/") || trimmedLc.StartsWith("http"))
                {
                    var entryId = entryUrlParser.Parse(trimmed, allowRelative: true);

                    if (entryId.EntryType == EntryType.Artist)
                    {
                        return new ParsedArtistQuery {
                                   Id = entryId.Id
                        }
                    }
                    ;
                }

                if (trimmedLc.StartsWith("http") || trimmedLc.StartsWith("mylist/") || trimmedLc.StartsWith("user/"))
                {
                    var extUrl = new ArtistExternalUrlParser().GetExternalUrl(trimmed);

                    if (extUrl != null)
                    {
                        return new ParsedArtistQuery {
                                   ExternalLinkUrl = extUrl
                        }
                    }
                    ;
                }
            }
            else
            {
                switch (term.PropertyName)
                {
                case "id":
                    return(new ParsedArtistQuery {
                        Id = PrimitiveParseHelper.ParseIntOrDefault(term.Value, 0)
                    });
                }
            }

            return(new ParsedArtistQuery {
                Name = textQuery.Query
            });
        }
Пример #27
0
 public void QueryNameMoveExactToTop()
 {
     _queryParams = _queryParams with
     {
         Common = _queryParams.Common with
         {
             TextQuery      = SearchTextQuery.Create("Tears"),
             MoveExactToTop = true,
         },
Пример #28
0
        public PartialFindResult <SongForApiContract> GetList(
            string query               = "",
            string songTypes           = null,
            [FromUri] string[] tagName = null,
            [FromUri] int[] tagId      = null,
            bool childTags             = false,
            [FromUri] int[] artistId   = null,
            ArtistAlbumParticipationStatus artistParticipationStatus = ArtistAlbumParticipationStatus.Everything,
            bool childVoicebanks            = false,
            bool includeMembers             = false,
            bool onlyWithPvs                = false,
            [FromUri] PVServices?pvServices = null,
            int?since            = null,
            int?minScore         = null,
            int?userCollectionId = null,
            int?releaseEventId   = null,
            EntryStatus?status   = null,
            [FromUri] AdvancedSearchFilter[] advancedFilters = null,
            int start                      = 0, int maxResults = defaultMax, bool getTotalCount = false,
            SongSortRule sort              = SongSortRule.Name,
            bool preferAccurateMatches     = false,
            NameMatchMode nameMatchMode    = NameMatchMode.Exact,
            SongOptionalFields fields      = SongOptionalFields.None,
            ContentLanguagePreference lang = ContentLanguagePreference.Default)
        {
            var textQuery = SearchTextQuery.Create(query, nameMatchMode);
            var types     = EnumVal <SongType> .ParseMultiple(songTypes);

            var param = new SongQueryParams(textQuery, types, start, Math.Min(maxResults, absoluteMax), getTotalCount, sort, false, preferAccurateMatches, null)
            {
                ArtistParticipation =
                {
                    ArtistIds       = artistId,
                    Participation   = artistParticipationStatus,
                    ChildVoicebanks = childVoicebanks,
                    IncludeMembers  = includeMembers
                },
                TagIds             = tagId,
                Tags               = tagName,
                ChildTags          = childTags,
                OnlyWithPVs        = onlyWithPvs,
                TimeFilter         = since.HasValue ? TimeSpan.FromHours(since.Value) : TimeSpan.Zero,
                MinScore           = minScore ?? 0,
                PVServices         = pvServices,
                UserCollectionId   = userCollectionId ?? 0,
                ReleaseEventId     = releaseEventId ?? 0,
                AdvancedFilters    = advancedFilters,
                LanguagePreference = lang
            };

            param.Common.EntryStatus = status;

            var artists = service.Find(s => new SongForApiContract(s, null, lang, fields), param);

            return(artists);
        }
Пример #29
0
        public void QueryTag()
        {
            queryParams.Common.TextQuery = SearchTextQuery.Create("tag:Electronic");

            var result = CallFind();

            Assert.AreEqual(1, result.Items.Length, "1 result");
            Assert.AreEqual(1, result.TotalCount, "1 total count");
            Assert.AreEqual(Db.Song, result.Items[0], "result is as expected");
        }
Пример #30
0
        public void QueryNameWords()
        {
            queryParams.Common.TextQuery = SearchTextQuery.Create("Tears Crystal", NameMatchMode.Words);

            var result = CallFind();

            Assert.AreEqual(1, result.Items.Length, "1 result");
            Assert.AreEqual(1, result.TotalCount, "total result count");
            Assert.AreEqual("Crystal Tears", result.Items[0].DefaultName);
        }