public void Gather(Document document)
        {
            if (document == null)
            {
                return;
            }

            if (_includes == null || _includes.Length == 0)
            {
                return;
            }

            if (_includedIds == null)
            {
                _includedIds = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
            }

            AddToIgnore(document.Id);

            foreach (var include in _includes)
            {
                if (include == Constants.Documents.Indexing.Fields.DocumentIdFieldName)
                {
                    _includedIds.Add(document.Id);
                    continue;
                }
                IncludeUtil.GetDocIdFromInclude(document.Data, new StringSegment(include), _includedIds);
            }
        }
Example #2
0
        private void AddEdgeAfterFiltering(Match left, BlittableJsonReaderObject leftDoc, StringSegment path)
        {
            var edgeIncludeOp = new EdgeIncludeOp(IncludedEdges);

            IncludedEdges.Clear();
            IncludeUtil.GetDocIdFromInclude(leftDoc,
                                            path,
                                            edgeIncludeOp);

            if (IncludedEdges.Count == 0)
            {
                return;
            }

            foreach (var includedEdge in IncludedEdges)
            {
                if (Right == null)
                {
                    MergeAndAddResult(left, leftDoc, includedEdge.Key, includedEdge.Value, default);
                    continue;
                }
                foreach (var rightMatch in Right.GetById(includedEdge.Key))
                {
                    MergeAndAddResult(left, leftDoc, includedEdge.Key, includedEdge.Value, rightMatch);
                }
            }
        }
Example #3
0
            private JsValue LoadDocumentByPath(JsValue self, JsValue[] args)
            {
                AssertValidDatabaseContext();


                if (args.Length != 2 ||
                    (args[0].IsNull() == false && args[0].IsUndefined() == false && args[0].IsObject() == false) ||
                    args[1].IsString() == false)
                {
                    throw new InvalidOperationException("loadPath(doc, path) must be called with a document and path");
                }

                if (args[0].IsNull() || args[1].IsUndefined())
                {
                    return(args[0]);
                }

                if (args[0].AsObject() is BlittableObjectInstance b)
                {
                    var path = args[1].AsString();
                    if (_documentIds == null)
                    {
                        _documentIds = new HashSet <string>();
                    }

                    _documentIds.Clear();
                    IncludeUtil.GetDocIdFromInclude(b.Blittable, path, _documentIds);
                    if (path.IndexOf("[]", StringComparison.InvariantCulture) != -1) // array
                    {
                        return(JsValue.FromObject(ScriptEngine, _documentIds.Select(LoadDocumentInternal).ToList()));
                    }
                    if (_documentIds.Count == 0)
                    {
                        return(JsValue.Null);
                    }

                    return(LoadDocumentInternal(_documentIds.First()));
                }

                throw new InvalidOperationException("loadPath(doc, path) must be called with a valid document instance, but got a JS object instead");
            }
        internal void Gather(Document document)
        {
            if (document == null)
            {
                return;
            }

            if (_includes == null || _includes.Length == 0)
            {
                return;
            }

            if (_includedKeys == null)
            {
                _includedKeys = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
            }

            foreach (var include in _includes)
            {
                IncludeUtil.GetDocIdFromInclude(document.Data, new StringSegment(include), _includedKeys, _database.IdentityPartsSeparator);
            }
        }
Example #5
0
        public void Gather(Document document)
        {
            if (document == null)
            {
                return;
            }

            if (_includes.Count == 0)
            {
                return;
            }

            if (_includedIds == null)
            {
                _includedIds = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
            }

            foreach (var include in _includes)
            {
                IncludeUtil.GetDocIdFromInclude(document.Data, new StringSegment(include, 0), _includedIds);
            }
        }
        protected bool TryGetValue(FieldsToFetch.FieldToFetch fieldToFetch, Document document, Lucene.Net.Documents.Document luceneDoc, IState state, Dictionary <string, IndexField> indexFields, bool?anyDynamicIndexFields, out string key, out object value)
        {
            key = fieldToFetch.ProjectedName ?? fieldToFetch.Name.Value;

            if (fieldToFetch.QueryField == null)
            {
                return(TryGetFieldValueFromDocument(document, fieldToFetch, out value));
            }

            if (fieldToFetch.QueryField.Function != null)
            {
                var args = new object[fieldToFetch.QueryField.FunctionArgs.Length + 1];
                for (int i = 0; i < fieldToFetch.FunctionArgs.Length; i++)
                {
                    TryGetValue(fieldToFetch.FunctionArgs[i], document, luceneDoc, state, indexFields, anyDynamicIndexFields, out _, out args[i]);
                    if (ReferenceEquals(args[i], document))
                    {
                        args[i] = Tuple.Create(document, luceneDoc, state, indexFields, anyDynamicIndexFields);
                    }
                }
                value = GetFunctionValue(fieldToFetch, document.Id, args);
                return(true);
            }

            if (fieldToFetch.QueryField.IsCounter)
            {
                string name;
                string id = document.Id;
                if (fieldToFetch.QueryField.IsParameter)
                {
                    if (_query.QueryParameters == null)
                    {
                        throw new InvalidQueryException("The query is parametrized but the actual values of parameters were not provided", _query.Query, null);
                    }

                    if (_query.QueryParameters.TryGetMember(fieldToFetch.QueryField.Name, out var nameObject) == false)
                    {
                        throw new InvalidQueryException($"Value of parameter '{fieldToFetch.QueryField.Name}' was not provided", _query.Query, _query.QueryParameters);
                    }

                    name = nameObject.ToString();
                    key  = fieldToFetch.QueryField.Alias ?? name;
                }
                else
                {
                    name = fieldToFetch.Name.Value;
                }

                if (fieldToFetch.QueryField.SourceAlias != null &&
                    BlittableJsonTraverser.Default.TryRead(document.Data, fieldToFetch.QueryField.SourceAlias, out var sourceId, out _))
                {
                    id = sourceId.ToString();
                }

                if (fieldToFetch.QueryField.FunctionArgs != null)
                {
                    value = GetCounterRaw(id, name);
                }
                else
                {
                    value = GetCounter(id, name);
                }

                return(true);
            }

            if (fieldToFetch.QueryField.ValueTokenType != null)
            {
                var val = fieldToFetch.QueryField.Value;
                if (fieldToFetch.QueryField.ValueTokenType.Value == ValueTokenType.Parameter)
                {
                    if (_query == null)
                    {
                        value = null;
                        return(false); // only happens for debug endpoints and more like this
                    }
                    _query.QueryParameters.TryGet((string)val, out val);
                }
                value = val;
                return(true);
            }

            if (fieldToFetch.QueryField.HasSourceAlias == false)
            {
                return(TryGetFieldValueFromDocument(document, fieldToFetch, out value));
            }
            if (_loadedDocumentIds == null)
            {
                _loadedDocumentIds          = new HashSet <string>();
                _loadedDocuments            = new Dictionary <string, Document>();
                _loadedDocumentsByAliasName = new Dictionary <string, Document>();
            }
            _loadedDocumentIds.Clear();

            //_loadedDocuments.Clear(); - explicitly not clearing this, we want to cache this for the duration of the query

            _loadedDocuments[document.Id ?? string.Empty] = document;
            if (fieldToFetch.QueryField.SourceAlias != null)
            {
                if (fieldToFetch.QueryField.IsQuoted)
                {
                    _loadedDocumentIds.Add(fieldToFetch.QueryField.SourceAlias);
                }
                else if (fieldToFetch.QueryField.IsParameter)
                {
                    if (_query.QueryParameters == null)
                    {
                        throw new InvalidQueryException("The query is parametrized but the actual values of parameters were not provided", _query.Query, (BlittableJsonReaderObject)null);
                    }

                    if (_query.QueryParameters.TryGetMember(fieldToFetch.QueryField.SourceAlias, out var id) == false)
                    {
                        throw new InvalidQueryException($"Value of parameter '{fieldToFetch.QueryField.SourceAlias}' was not provided", _query.Query, _query.QueryParameters);
                    }

                    _loadedDocumentIds.Add(id.ToString());
                }
                else if (fieldToFetch.QueryField.LoadFromAlias != null)
                {
                    if (_loadedDocumentsByAliasName.TryGetValue(fieldToFetch.QueryField.LoadFromAlias, out var loadedDoc))
                    {
                        IncludeUtil.GetDocIdFromInclude(loadedDoc.Data, fieldToFetch.QueryField.SourceAlias, _loadedDocumentIds, _database.IdentityPartsSeparator);
                    }
                }
                else if (fieldToFetch.CanExtractFromIndex)
                {
                    if (luceneDoc != null)
                    {
                        var field = luceneDoc.GetField(fieldToFetch.QueryField.SourceAlias);
                        if (field != null)
                        {
                            var fieldValue = ConvertType(_context, field, GetFieldType(field.Name, luceneDoc), state);
                            _loadedDocumentIds.Add(fieldValue.ToString());
                        }
                    }
                }
                else
                {
                    IncludeUtil.GetDocIdFromInclude(document.Data, fieldToFetch.QueryField.SourceAlias, _loadedDocumentIds, _database.IdentityPartsSeparator);
                }
            }
            else
            {
                _loadedDocumentIds.Add(document.Id ?? string.Empty); // null source alias is the root doc
                _loadedDocumentsByAliasName.Clear();
            }

            if (_loadedDocumentIds.Count == 0)
            {
                if (fieldToFetch.QueryField.SourceIsArray)
                {
                    value = new List <object>();
                    return(true);
                }
                value = null;
                return(false);
            }

            var buffer = new List <object>();

            foreach (var docId in _loadedDocumentIds)
            {
                if (docId == null)
                {
                    continue;
                }

                if (_loadedDocuments.TryGetValue(docId, out var doc) == false)
                {
                    using (_loadScope = _loadScope?.Start() ?? _projectionScope?.For(nameof(QueryTimingsScope.Names.Load)))
                        _loadedDocuments[docId] = doc = LoadDocument(docId);
                }
                if (doc == null)
                {
                    continue;
                }

                if (fieldToFetch.QueryField.Alias != null)
                {
                    _loadedDocumentsByAliasName[fieldToFetch.QueryField.Alias] = doc;
                }

                if (string.IsNullOrEmpty(fieldToFetch.Name.Value)) // we need the whole document here
                {
                    buffer.Add(doc);
                    continue;
                }
                if (TryGetFieldValueFromDocument(doc, fieldToFetch, out var val))
                {
                    if (val is string == false && val is LazyStringValue == false && val is System.Collections.IEnumerable items)
                    {
                        // we flatten arrays in projections
                        foreach (var item in items)
                        {
                            buffer.Add(item);
                        }

                        fieldToFetch.QueryField.SourceIsArray = true;
                    }
                    else
                    {
                        buffer.Add(val);
                    }
                }
            }

            if (fieldToFetch.QueryField.SourceIsArray)
            {
                value = buffer;
                return(true);
            }
            if (buffer.Count > 0)
            {
                if (buffer.Count > 1)
                {
                    ThrowOnlyArrayFieldCanHaveMultipleValues(fieldToFetch);
                }
                value = buffer[0];
                return(true);
            }
            value = null;
            return(false);
        }
Example #7
0
        public void Gather(List <FacetResult> results)
        {
            if (results == null || results.Count == 0)
            {
                return;
            }

            if (_includes == null || _includes.Length == 0)
            {
                return;
            }

            if (_includedIds == null)
            {
                _includedIds = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
            }

            foreach (var include in _includes)
            {
                string path  = null;
                var    match = results.FirstOrDefault(x => x.Name == include);
                if (match == null)
                {
                    int firstDot = include.IndexOf('.');
                    if (firstDot == -1)
                    {
                        continue;
                    }
                    string name = include.Substring(0, firstDot);
                    match = results.FirstOrDefault(x => x.Name == name);
                    if (match == null)
                    {
                        continue;
                    }
                    path = include.Substring(firstDot + 1);
                }
                foreach (FacetValue value in match.Values)
                {
                    if (path == null)
                    {
                        _includedIds.Add(value.Range);
                    }
                    else
                    {
                        BlittableJsonReaderObject json;
                        try
                        {
                            json = _context.ReadForMemory(value.Range, "Facet/Object");
                        }
                        catch (Exception e)
                        {
                            // expected, we can ignore this
                            continue;
                        }

                        using (json)
                        {
                            IncludeUtil.GetDocIdFromInclude(json, new StringSegment(path), _includedIds, _context.DocumentDatabase.IdentityPartsSeparator);
                        }
                    }
                }
            }
        }
Example #8
0
        private bool TryGetValue(FieldsToFetch.FieldToFetch fieldToFetch, Document document, Lucene.Net.Documents.Document luceneDoc, IState state, out object value)
        {
            if (fieldToFetch.QueryField == null)
            {
                return(TryGetFieldValueFromDocument(document, fieldToFetch, out value));
            }

            if (fieldToFetch.QueryField.Function != null)
            {
                var args = new object[fieldToFetch.QueryField.FunctionArgs.Length + 1];
                for (int i = 0; i < fieldToFetch.FunctionArgs.Length; i++)
                {
                    TryGetValue(fieldToFetch.FunctionArgs[i], document, luceneDoc, state, out args[i]);
                    if (ReferenceEquals(args[i], document))
                    {
                        args[i] = Tuple.Create(document, luceneDoc, state);
                    }
                }

                args[args.Length - 1] = _query.QueryParameters;

                value = InvokeFunction(
                    fieldToFetch.QueryField.Name,
                    _query.Metadata.Query,
                    args);
                return(true);
            }

            if (fieldToFetch.QueryField.ValueTokenType != null)
            {
                var val = fieldToFetch.QueryField.Value;
                if (fieldToFetch.QueryField.ValueTokenType.Value == ValueTokenType.Parameter)
                {
                    if (_query == null)
                    {
                        value = null;
                        return(false); // only happens for debug endpoints and more like this
                    }
                    _query.QueryParameters.TryGet((string)val, out val);
                }
                value = val;
                return(true);
            }

            if (fieldToFetch.QueryField.HasSourceAlias == false)
            {
                return(TryGetFieldValueFromDocument(document, fieldToFetch, out value));
            }
            if (_loadedDocumentIds == null)
            {
                _loadedDocumentIds = new HashSet <string>();
                _loadedDocuments   = new Dictionary <string, Document>();
            }
            _loadedDocumentIds.Clear();

            //_loadedDocuments.Clear(); - explicitly not clearing this, we want to cahce this for the duration of the query


            _loadedDocuments[document.Id ?? string.Empty] = document;
            if (fieldToFetch.QueryField.SourceAlias != null)
            {
                IncludeUtil.GetDocIdFromInclude(document.Data, fieldToFetch.QueryField.SourceAlias, _loadedDocumentIds);
            }
            else
            {
                _loadedDocumentIds.Add(document.Id ?? string.Empty); // null source alias is the root doc
            }
            if (_loadedDocumentIds.Count == 0)
            {
                value = null;
                return(false);
            }

            var buffer = new List <object>();

            foreach (var docId in _loadedDocumentIds)
            {
                if (docId == null)
                {
                    continue;
                }

                if (_loadedDocuments.TryGetValue(docId, out var doc) == false)
                {
                    _loadedDocuments[docId] = doc = LoadDocument(docId);
                }
                if (doc == null)
                {
                    continue;
                }
                if (string.IsNullOrEmpty(fieldToFetch.Name)) // we need the whole document here
                {
                    buffer.Add(doc);
                    continue;
                }
                if (TryGetFieldValueFromDocument(doc, fieldToFetch, out var val))
                {
                    buffer.Add(val);
                }
            }

            if (fieldToFetch.QueryField.SourceIsArray)
            {
                value = buffer;
                return(true);
            }
            if (buffer.Count > 0)
            {
                if (buffer.Count > 1)
                {
                    ThrowOnlyArrayFieldCanHaveMultipleValues(fieldToFetch);
                }
                value = buffer[0];
                return(true);
            }
            value = null;
            return(false);
        }
        private bool TryGetValue(FieldsToFetch.FieldToFetch fieldToFetch, Document document, Lucene.Net.Documents.Document luceneDoc, IState state, out object value)
        {
            if (fieldToFetch.QueryField == null)
            {
                return(TryGetFieldValueFromDocument(document, fieldToFetch, out value));
            }

            if (fieldToFetch.QueryField.Function != null)
            {
                var args = new object[fieldToFetch.QueryField.FunctionArgs.Length + 1];
                for (int i = 0; i < fieldToFetch.FunctionArgs.Length; i++)
                {
                    TryGetValue(fieldToFetch.FunctionArgs[i], document, luceneDoc, state, out args[i]);
                    if (ReferenceEquals(args[i], document))
                    {
                        args[i] = Tuple.Create(document, luceneDoc, state);
                    }
                }

                args[args.Length - 1] = _query.QueryParameters;

                value = InvokeFunction(
                    fieldToFetch.QueryField.Name,
                    _query.Metadata.Query,
                    args);
                return(true);
            }

            if (fieldToFetch.QueryField.ValueTokenType != null)
            {
                var val = fieldToFetch.QueryField.Value;
                if (fieldToFetch.QueryField.ValueTokenType.Value == ValueTokenType.Parameter)
                {
                    if (_query == null)
                    {
                        value = null;
                        return(false); // only happens for debug endpoints and more like this
                    }
                    _query.QueryParameters.TryGet((string)val, out val);
                }
                value = val;
                return(true);
            }

            if (fieldToFetch.QueryField.HasSourceAlias == false)
            {
                return(TryGetFieldValueFromDocument(document, fieldToFetch, out value));
            }
            if (_loadedDocumentIds == null)
            {
                _loadedDocumentIds          = new HashSet <string>();
                _loadedDocuments            = new Dictionary <string, Document>();
                _loadedDocumentsByAliasName = new Dictionary <string, Document>();
            }
            _loadedDocumentIds.Clear();

            //_loadedDocuments.Clear(); - explicitly not clearing this, we want to cache this for the duration of the query

            _loadedDocuments[document.Id ?? string.Empty] = document;
            if (fieldToFetch.QueryField.SourceAlias != null)
            {
                if (fieldToFetch.QueryField.IsQuoted)
                {
                    _loadedDocumentIds.Add(fieldToFetch.QueryField.SourceAlias);
                }

                else if (fieldToFetch.QueryField.IsParameter)
                {
                    if (_query.QueryParameters == null)
                    {
                        throw new InvalidQueryException("The query is parametrized but the actual values of parameters were not provided", _query.Query, (BlittableJsonReaderObject)null);
                    }

                    if (_query.QueryParameters.TryGetMember(fieldToFetch.QueryField.SourceAlias, out var id) == false)
                    {
                        throw new InvalidQueryException($"Value of parameter '{fieldToFetch.QueryField.SourceAlias}' was not provided", _query.Query, _query.QueryParameters);
                    }

                    _loadedDocumentIds.Add(id.ToString());
                }

                else if (fieldToFetch.QueryField.LoadFromAlias != null)
                {
                    if (_loadedDocumentsByAliasName.TryGetValue(fieldToFetch.QueryField.LoadFromAlias, out var loadedDoc))
                    {
                        IncludeUtil.GetDocIdFromInclude(loadedDoc.Data, fieldToFetch.QueryField.SourceAlias, _loadedDocumentIds);
                    }
                }

                else
                {
                    IncludeUtil.GetDocIdFromInclude(document.Data, fieldToFetch.QueryField.SourceAlias, _loadedDocumentIds);
                }
            }
            else
            {
                _loadedDocumentIds.Add(document.Id ?? string.Empty); // null source alias is the root doc
                _loadedDocumentsByAliasName.Clear();
            }

            if (_loadedDocumentIds.Count == 0)
            {
                if (fieldToFetch.QueryField.SourceIsArray)
                {
                    value = new List <object>();
                    return(true);
                }
                value = null;
                return(false);
            }

            var buffer = new List <object>();

            foreach (var docId in _loadedDocumentIds)
            {
                if (docId == null)
                {
                    continue;
                }

                if (_loadedDocuments.TryGetValue(docId, out var doc) == false)
                {
                    _loadedDocuments[docId] = doc = LoadDocument(docId);
                }
                if (doc == null)
                {
                    continue;
                }

                if (fieldToFetch.QueryField.Alias != null)
                {
                    _loadedDocumentsByAliasName[fieldToFetch.QueryField.Alias] = doc;
                }

                if (string.IsNullOrEmpty(fieldToFetch.Name)) // we need the whole document here
                {
                    buffer.Add(doc);
                    continue;
                }
                if (TryGetFieldValueFromDocument(doc, fieldToFetch, out var val))
                {
                    if (val is string == false && val is System.Collections.IEnumerable items)
                    {
                        // we flatten arrays in projections
                        foreach (var item in items)
                        {
                            buffer.Add(item);
                        }

                        fieldToFetch.QueryField.SourceIsArray = true;
                    }
                    else
                    {
                        buffer.Add(val);
                    }
                }
            }

            if (fieldToFetch.QueryField.SourceIsArray)
            {
                value = buffer;
                return(true);
            }
            if (buffer.Count > 0)
            {
                if (buffer.Count > 1)
                {
                    ThrowOnlyArrayFieldCanHaveMultipleValues(fieldToFetch);
                }
                value = buffer[0];
                return(true);
            }
            value = null;
            return(false);
        }