public IEnumerable <PrcRecommendationResult> RecommendById(string id, PrcSettingsElastic prcSettings, PrcRecommendationByIdRequest request)
        {
            var result             = new List <PrcRecommendationResult>();
            var globalStoreDataSet = GlobalStore.DataSets.Get(prcSettings.DataSetName);
            var dataSet            = globalStoreDataSet.DataSet;

            var documentQuery           = queryFactory.GetDocumentQuery(dataSet.Name);
            var fieldsForRecommendation = prcSettings.FieldsForRecommendation;

            var filterOrWeight = !string.IsNullOrEmpty(request.Query) || request?.Weights?.Any() == true;

            var tagId = string.Empty;

            if (string.IsNullOrEmpty(request.TagId))
            {
                var documentElastic = documentQuery.Get(request.DocumentId);
                if (documentElastic == null)
                {
                    return(result);
                }
                var tagToken = JTokenHelper.GetToken(documentElastic.DocumentObject).GetPathToken(dataSet.TagField);
                tagId = JTokenHelper.GetUnderlyingToken(tagToken)?.ToString();
                if (tagId == null)
                {
                    return(result);
                }
            }
            else
            {
                tagId = request.TagId;
            }

            var similarDocIdsWithScore = redisHandler.GetTopNDocuments(new PrcIndexRedisKey(id, tagId, request.DocumentId), filterOrWeight ? -1 : request.Count - 1);

            Dictionary <string, double> resultDictionary = similarDocIdsWithScore;

            var documentElastics = (filterOrWeight || request.NeedDocumentInResult) ?
                                   GetDocuments(dataSet.Name, request.Query, null, fieldsForRecommendation, similarDocIdsWithScore.Keys, request.NeedDocumentInResult) :
                                   null;

            // ha a Filter és a Weights is üres, a TOP Count doksi Id - t visszaadjuk score-jaikkal. (ha kell a document is, akkor elastic - tól elkérjük ezeket pluszban)
            if (filterOrWeight)
            {
                // ezekre a doksikra módosítjuk a prc score - t a Weights-el
                var docIdsWithScore = documentElastics.ToDictionary(k => k.Id, v => similarDocIdsWithScore[v.Id]);

                //súlyozás
                if (request?.Weights?.Any() == true)
                {
                    var weightsDic = request.Weights.ToDictionary(key => Guid.NewGuid().ToString(), value => value);

                    var docIds  = docIdsWithScore.Keys.ToList();
                    var queries = weightsDic.ToDictionary(key => key.Key, value => documentQuery.PrefixQueryFields(value.Value.Query, globalStoreDataSet.DocumentFields));
                    var ids     = documentQuery.GetExistsForQueries(queries, docIds).ToDictionary(k => k.Key, v => v.Value.ToDictionary(ke => ke, va => va));

                    var allWeightsCount = request.Weights.Count;
                    foreach (var docId in docIds)
                    {
                        var weightsSum = weightsDic.Where(w => ids[w.Key].ContainsKey(docId)).Sum(w => w.Value.Value);
                        var pow        = 1 + (weightsSum / allWeightsCount);
                        var score      = Math.Pow(docIdsWithScore[docId] + 1, pow) - 1;
                        docIdsWithScore[docId] = score;
                    }
                }

                resultDictionary = docIdsWithScore;
            }

            var recommendation = resultDictionary
                                 .OrderByDescending(o => o.Value)
                                 .Take(request.Count)
                                 .Select(s => new PrcRecommendationResult()
            {
                DocumentId = s.Key,
                Score      = s.Value,
                Document   = request.NeedDocumentInResult ? documentElastics.SingleOrDefault(d => d.Id == s.Key).DocumentObject : null
            });

            return(recommendation);
        }
Пример #2
0
        private void AddGlobalStoreInternal(string name, string indexName, DataSet dataSet)
        {
            var paths        = new List <string>();
            var attachments  = new List <string>();
            var tagIsArray   = false;
            var tagIsInteger = false;

            if (dataSet.SampleDocument != null)
            {
                var pathTokens = DocumentHelper.GetAllPathTokens(dataSet.SampleDocument);
                paths = pathTokens.Keys.ToList();

                if (!pathTokens.ContainsKey(dataSet.TagField))
                {
                    throw new InvalidOperationException($"DataSet Name: ´{name}´, Index: ´{indexName}´. SampleDocument does not contain TagField ´{dataSet.TagField}´");
                }

                var tagToken = pathTokens[dataSet.TagField];
                tagIsArray = tagToken.Type == JTokenType.Array;

                if (tagIsArray)
                {
                    tagIsInteger = JTokenHelper.GetUnderlyingToken(tagToken).Type == JTokenType.Integer;
                }
                else
                {
                    tagIsInteger = tagToken.Type == JTokenType.Integer;
                }
            }
            else if (dataSet.Schema != null)
            {
                var pathDictionary = SchemaHelper.GetPaths(dataSet.Schema);

                paths       = pathDictionary.Keys.ToList();
                attachments = pathDictionary
                              .Where(kv => kv.Value.Item1 == SchemaHelper.Types.Attachment)
                              .Select(kv => kv.Key)
                              .ToList();

                if (!pathDictionary.ContainsKey(dataSet.TagField))
                {
                    throw new InvalidOperationException($"DataSet Name: ´{name}´, Index: ´{indexName}´. Schema does not contain TagField ´{dataSet.TagField}´");
                }

                var tagTuple = pathDictionary[dataSet.TagField];
                tagIsArray = SchemaHelper.IsArray(tagTuple.Item1);
                if (tagIsArray)
                {
                    tagIsInteger = SchemaHelper.IsInteger(tagTuple.Item2);
                }
                else
                {
                    tagIsInteger = SchemaHelper.IsInteger(tagTuple.Item1);
                }
            }
            else
            {
                throw new InvalidOperationException("DataSet has no SampleDocument nor Schema property");
            }

            GlobalStore.DataSets.Add(name ?? indexName, new GlobalStoreDataSet(name, indexName, dataSet, paths, tagIsArray, tagIsInteger, attachments));
        }