예제 #1
0
        public IIndexer <EventLog <TEventDTO> > CreateIndexerForEventLog <TEventDTO>(string indexName, int documentsPerBatch)
            where TEventDTO : class, IEventDTO, new()
        {
            var indexDefinition = new EventIndexDefinition <TEventDTO>(indexName);
            var indexer         = new ElasticEventIndexer <TEventDTO>(indexName, _elasticClient, indexDefinition, documentsPerBatch);

            _indexers.Add(indexer);
            return(indexer);
        }
        public async Task <IEventIndexer <TEvent> > CreateEventIndexer <TEvent>(EventIndexDefinition <TEvent> searchIndexDefinition) where TEvent : class
        {
            await CreateIfNotExists(searchIndexDefinition);

            var indexer =
                new ElasticEventIndexer <TEvent>(_elasticClient, searchIndexDefinition);

            return(indexer);
        }
예제 #3
0
        public IIndexer <EventLog <TEventDTO> > CreateIndexerForEventLog <TEventDTO>(
            string indexName, int documentsPerBatch = 1)
            where TEventDTO : class, IEventDTO, new()
        {
            var indexClient     = GetOrCreateIndexClient(indexName);
            var indexDefinition = new EventIndexDefinition <TEventDTO>(indexName);
            var azureIndexer    = new AzureEventIndexer <TEventDTO>(indexClient, indexDefinition, documentsPerBatch);

            _indexers.Add(azureIndexer);
            return(azureIndexer);
        }
예제 #4
0
        public void WillIndexDtoWithOnlySearchFieldAttributes()
        {
            var searchIndex = new EventIndexDefinition <DtoWithoutParameterAttributes>(addPresetEventLogFields: false);

            var dto = new DtoWithoutParameterAttributes
            {
                Name     = "Test",
                Metadata = new MetadataDto {
                    Id = "A1", Description = "first description"
                },
                Tags = new List <TagDto>
                {
                    new TagDto()
                    {
                        Value = "Category A"
                    },
                    new TagDto()
                    {
                        Value = "Category B"
                    }
                },
                Values = new List <int>()
                {
                    1, 2, 3
                }
            };

            Assert.Equal("CustomIndexA", searchIndex.IndexName);

            Assert.Equal(5, searchIndex.Fields.Length);

            var eventLog = new EventLog <DtoWithoutParameterAttributes>(dto, null);

            searchIndex
            .Assertions(eventLog)
            .HasField(nameof(dto.Name),
                      f => f.ReturnsValue(dto.Name))
            .HasField(nameof(dto.Values),
                      f => f.IsCollection(),
                      f => f.ReturnsValue <int[]>(actualValues => (dto.Values.ToCommaSeparatedString(), actualValues.ToCommaSeparatedString())))
            .HasField($"{nameof(dto.Metadata)}.{nameof(dto.Metadata.Id)}",
                      f => f.HasFlags(isSearchable: true),
                      f => f.ReturnsValue(dto.Metadata.Id))
            .HasField($"{nameof(dto.Metadata)}.{nameof(dto.Metadata.Description)}",
                      f => f.HasFlags().ReturnsValue(dto.Metadata.Description))
            .HasField($"{nameof(dto.Tags)}.Value",
                      f => f.HasFlags(isCollection: true, isSearchable: true, isFilterable: true),
                      f => f.ReturnsValue <string[]>(actualTags => (dto.Tags.Select(item => item.Value).ToCommaSeparatedString(), actualTags.ToCommaSeparatedString()))
                      );
        }
예제 #5
0
        public void EventParametersCanBeCustomIndexed()
        {
            var searchIndex    = new EventIndexDefinition <CustomEventDtoB>();
            var customEventDto = new CustomEventDtoB()
            {
                Sender = "Charles"
            };
            var eventLog = new EventLog <CustomEventDtoB>(customEventDto, null);

            searchIndex.Assertions(eventLog)
            .HasField("SenderAddress")
            .HasFlags(isSearchable: true, isSortable: true)
            .ReturnsValue(customEventDto.Sender);
        }
예제 #6
0
        public void WillIndexNewProperties()
        {
            var searchIndex = new EventIndexDefinition <CustomEventDtoE>();

            Assert.NotNull(searchIndex.Field("Sender"));

            const string sender = "Test";
            var          dto    = new CustomEventDtoE {
                Sender = Encoding.ASCII.GetBytes(sender)
            };
            var valueAsBytes  = searchIndex.Field("Sender").GetValue(dto) as byte[];
            var valueAsString = Encoding.ASCII.GetString(valueAsBytes);

            Assert.Equal(sender, valueAsString);
        }
예제 #7
0
        public void IndexCanIncludeCustomFieldsOutsideOfTheSolidityEvent()
        {
            var searchIndex = new EventIndexDefinition <CustomEventDtoA>();

            var customEventDto = new CustomEventDtoA()
            {
                Category = "CatA"
            };

            searchIndex
            .Assertions(new EventLog <CustomEventDtoA>(customEventDto, null))
            .HasField(nameof(customEventDto.Category),
                      f => f.IsString(),
                      f => f.HasFlags(isFacetable: true, isSearchable: true, isFilterable: true, isSortable: true),
                      f => f.ReturnsValue(customEventDto.Category));
        }
        public static object ToAzureDocument <TEvent>(this EventLog <TEvent> log, EventIndexDefinition <TEvent> indexDefinition) where TEvent : class
        {
            var dictionary = new Dictionary <string, object>();

            foreach (var field in indexDefinition.Fields)
            {
                var azureField = field.ToAzureField();

                var val = field.GetValue(log)?.ToAzureFieldValue();
                if (val != null)
                {
                    dictionary.Add(azureField.Name, val);
                }
            }

            return(dictionary);
        }
예제 #9
0
        public async Task MapsEventDtoToGenericSearchDocument()
        {
            var indexDefinition       = new EventIndexDefinition <TransferEvent>();
            var index                 = indexDefinition.ToAzureIndex();
            var mockSearchIndexClient = new SearchIndexClientMock <GenericSearchDocument>();

            var indexer = new AzureEventIndexer <TransferEvent>(
                mockSearchIndexClient.SearchIndexClient, indexDefinition);

            var eventLog = TestData.Contracts.StandardContract.SampleTransferEventLog();

            await indexer.IndexAsync(eventLog);

            Assert.Single(mockSearchIndexClient.IndexedBatches);
            var firstIndexAction = mockSearchIndexClient.IndexedBatches[0].Actions.First();

            Assert.Equal(eventLog.Log.Key(), firstIndexAction.Document[PresetSearchFieldName.log_key.ToString()]);
        }
예제 #10
0
        public async Task MapsEventDtoToGenericSearchDocument()
        {
            var indexDefinition   = new EventIndexDefinition <TransferEvent>();
            var mockElasticClient = new MockElasticClient();

            var indexer = new ElasticEventIndexer <TransferEvent>(
                "Transfers", mockElasticClient.ElasticClient, indexDefinition);

            var eventLog = TestData.Contracts.StandardContract.SampleTransferEventLog();

            await indexer.IndexAsync(eventLog);

            Assert.Single(mockElasticClient.BulkRequests);
            var actualOperation = mockElasticClient.GetFirstBulkOperation();

            Assert.NotNull(actualOperation);
            Assert.Equal("index", actualOperation.Operation);
            Assert.Equal(typeof(GenericSearchDocument), actualOperation.ClrType);
        }
        public static GenericSearchDocument ToGenericElasticSearchDoc <TEvent>(
            this EventLog <TEvent> log,
            EventIndexDefinition <TEvent> indexDefinition) where TEvent : class
        {
            var dictionary = new GenericSearchDocument();

            foreach (var field in indexDefinition.Fields)
            {
                var val = field.GetEventLogValue(log)?.ToElasticSearchFieldValue();
                if (val != null)
                {
                    dictionary.Add(field.Name.ToElasticName(), val);
                }
            }

            var id = indexDefinition.KeyField().GetEventLogValue(log);

            dictionary.SetId(id.ToString());

            return(dictionary);
        }
        public void ToAzureDocument_CreatesDictionaryFromEventLogUsingIndexDefinition()
        {
            var indexDefinition = new EventIndexDefinition <TransferEvent>();

            var eventLog = new EventLog <TransferEvent>(
                new TransferEvent
            {
                From  = "0x9209b29f2094457d3dba62d1953efea58176ba27",
                To    = "0x1209b29f2094457d3dba62d1953efea58176ba28",
                Value = new HexBigInteger(2000000)
            },
                new FilterLog
            {
                Address          = "0x26bc47888b7bfdf77db41ec0a2fb4db00af1c92a",
                TransactionHash  = "0xcb00b69d2594a3583309f332ada97d0df48bae00170e36a4f7bbdad7783fc7e5",
                BlockNumber      = new HexBigInteger(7118507),
                BlockHash        = "0x337cd6feedafac6abba40eff40fb1957e08985180f5a03016924ef72fc7b04b9",
                LogIndex         = new HexBigInteger(0),
                Removed          = false,
                TransactionIndex = new HexBigInteger(0)
            });

            var doc = eventLog.ToAzureDocument(indexDefinition);

            Assert.IsType <GenericSearchDocument>(doc);
            var dictionary = doc as GenericSearchDocument;

            Assert.Equal(eventLog.Event.From, dictionary["from"]);
            Assert.Equal(eventLog.Event.To, dictionary["to"]);
            Assert.Equal(eventLog.Event.Value.ToString(), dictionary["value"]);

            Assert.Equal(eventLog.Log.Address, dictionary[PresetSearchFieldName.log_address.ToString()]);
            Assert.Equal(eventLog.Log.TransactionHash, dictionary[PresetSearchFieldName.log_transaction_hash.ToString()]);
            Assert.Equal(eventLog.Log.BlockNumber.Value.ToString(), dictionary[PresetSearchFieldName.log_block_number.ToString()]);
            Assert.Equal(eventLog.Log.BlockHash, dictionary[PresetSearchFieldName.log_block_hash.ToString()]);
            Assert.Equal(eventLog.Log.LogIndex.Value.ToString(), dictionary[PresetSearchFieldName.log_log_index.ToString()]);
            Assert.Equal(eventLog.Log.Removed, dictionary[PresetSearchFieldName.log_removed.ToString()]);
            Assert.Equal(eventLog.Log.TransactionIndex.Value.ToString(), dictionary[PresetSearchFieldName.log_transaction_index.ToString()]);
        }
        public async Task CreateIndex_Upsert_Suggest_Search()
        {
            ConfigurationUtils.SetEnvironment("development");

            var appConfig = ConfigurationUtils
                            .Build(Array.Empty <string>(), userSecretsId: "Nethereum.BlockchainStore.Search.Tests");

            var apiKey = appConfig[ApiKeyName];

            var eventSearchIndexDefinition = new EventIndexDefinition <TransferEvent>();

            using (var searchService = new AzureSearchService(AzureSearchServiceName, apiKey))
            {
                try
                {
                    await searchService.DeleteIndexAsync(eventSearchIndexDefinition);

                    using (var azureIndex = await searchService.GetOrCreateIndex(eventSearchIndexDefinition))
                    {
                        var transferEventLog = new EventLog <TransferEvent>(
                            new TransferEvent
                        {
                            From   = "0x9209b29f2094457d3dba62d1953efea58176ba27",
                            To     = "0x1209b29f2094457d3dba62d1953efea58176ba28",
                            Value  = new HexBigInteger("2000000"),
                            Detail = new TransferDetail
                            {
                                Description = "A generic transfer",
                                Tags        = new List <Tag>
                                {
                                    new Tag {
                                        Name = "Status", Value = "Good"
                                    },
                                    new Tag {
                                        Name = "Year", Value = "2019"
                                    }
                                }
                            }
                        },
                            new FilterLog
                        {
                            Address          = "0x26bc47888b7bfdf77db41ec0a2fb4db00af1c92a",
                            TransactionHash  = "0xcb00b69d2594a3583309f332ada97d0df48bae00170e36a4f7bbdad7783fc7e5",
                            BlockNumber      = new HexBigInteger(7118507),
                            BlockHash        = "0x337cd6feedafac6abba40eff40fb1957e08985180f5a03016924ef72fc7b04b9",
                            LogIndex         = new HexBigInteger(0),
                            Removed          = false,
                            TransactionIndex = new HexBigInteger(0)
                        });

                        await azureIndex.IndexAsync(transferEventLog);

                        await Task.Delay(TimeSpan.FromSeconds(5));

                        var suggestion = await azureIndex.SuggestAsync(transferEventLog.Log.BlockNumber.Value.ToString());

                        Assert.NotNull(suggestion);
                        Assert.Equal(1, suggestion.Results.Count);

                        var searchResult = await azureIndex.SearchAsync(
                            transferEventLog.Event.From);

                        Assert.NotNull(searchResult);
                        Assert.Equal(1, searchResult.Results.Count);
                    }
                }
                finally
                {
                    await searchService.DeleteIndexAsync(eventSearchIndexDefinition);
                }
            }
        }
        public async Task <IEventIndexer <TEvent> > CreateEventIndexer <TEvent>(string indexName = null, bool addPresetEventLogFields = true) where TEvent : class
        {
            var eventIndexDefinition = new EventIndexDefinition <TEvent>(indexName, addPresetEventLogFields);

            return(await CreateEventIndexer(eventIndexDefinition));
        }
예제 #15
0
        public void BuildsExpectedIndexForCodeGeneratedEventDto()
        {
            var searchIndex = new EventIndexDefinition <DepositedEventDTO>();

            var depositedEventDto = new DepositedEventDTO
            {
                NewBalance = new HexBigInteger("100"),
                Value      = new HexBigInteger("10"),
                Sender     = "adsfadsfasdfasdf",
                Detail     = new DepositDetailDTO
                {
                    Currency   = "GBP",
                    Timestamp  = DateTimeOffset.UnixEpoch.ToUnixTimeSeconds(),
                    Categories = new List <CategoryDTO>
                    {
                        new CategoryDTO {
                            Name = "Dodgy"
                        },
                        new CategoryDTO {
                            Name = "International"
                        }
                    },
                    Tags = new List <string> {
                        "A", "B"
                    }
                }
            };

            var filterLog = new FilterLog
            {
                Type             = "type",
                Address          = "address",
                BlockHash        = "block_hash",
                BlockNumber      = new HexBigInteger(101),
                TransactionHash  = "transaction_hash",
                TransactionIndex = new HexBigInteger(3),
                LogIndex         = new HexBigInteger(9),
                Removed          = false
            };

            var eventLog = new EventLog <DepositedEventDTO>(depositedEventDto, filterLog);

            Assert.Equal("Deposited", searchIndex.IndexName);
            Assert.Equal(18, searchIndex.Fields.Length);

            searchIndex
            .Assertions(eventLog)
            .HasField(nameof(depositedEventDto.Sender),
                      f => f.IsString(),
                      f => f.HasFlags(isSearchable: true, isFacetable: true, isFilterable: true, isSortable: true),
                      f => f.ReturnsValue(depositedEventDto.Sender))
            .HasField(nameof(depositedEventDto.Value),
                      f => f.DataType <BigInteger>(),
                      f => f.HasFlags(),
                      f => f.ReturnsValue(depositedEventDto.Value))
            .HasField(nameof(depositedEventDto.NewBalance),
                      f => f.DataType <BigInteger>(),
                      f => f.HasFlags(),
                      f => f.ReturnsValue(depositedEventDto.NewBalance))
            .HasField("Detail.Currency",
                      f => f.IsString(),
                      f => f.HasFlags(isSearchable: true, isFilterable: true, isFacetable: true),
                      f => f.ReturnsValue(depositedEventDto.Detail.Currency))
            .HasField("Detail.Categories.Name",
                      f => f.IsString(),
                      f => f.ReturnsValue <string[]>(categoryNameArray =>
            {
                var x = depositedEventDto.Detail.Categories.Select(cat => cat.Name).ToCommaSeparatedString();
                var y = categoryNameArray.ToCommaSeparatedString();
                return(x, y);
            }))
            .HasField("Detail.Tags",
                      f => f.DataType <List <string> >(),
                      f => f.HasFlags(isCollection: true),
                      f => f.ReturnsValue <string[]>(tags =>
            {
                var x = depositedEventDto.Detail.Tags.ToCommaSeparatedString();
                var y = tags.ToCommaSeparatedString();
                return(x, y);
            }))
            .HasField(PresetSearchFieldName.log_key,
                      f => f.IsString(),
                      f => f.HasFlags(isKey: true, isSortable: true),
                      f => f.ReturnsValue(filterLog.Key()))
            .HasField(PresetSearchFieldName.log_removed,
                      f => f.DataType <bool>(),
                      f => f.HasFlags(isFilterable: true, isSortable: true),
                      f => f.ReturnsValue(filterLog.Removed))
            .HasField(PresetSearchFieldName.log_type,
                      f => f.IsString(),
                      f => f.HasFlags(isFilterable: true, isSortable: true),
                      f => f.ReturnsValue(filterLog.Type))
            .HasField(PresetSearchFieldName.log_log_index,
                      f => f.IsHexBigInteger(),
                      f => f.HasFlags(isFilterable: true),
                      f => f.ReturnsValue(filterLog.LogIndex))
            .HasField(PresetSearchFieldName.log_transaction_hash,
                      f => f.IsString(),
                      f => f.HasFlags(isSearchable: true, isFilterable: true, isFacetable: true),
                      f => f.ReturnsValue(filterLog.TransactionHash))
            .HasField(PresetSearchFieldName.log_transaction_index,
                      f => f.IsHexBigInteger(),
                      f => f.HasFlags(isFilterable: true),
                      f => f.ReturnsValue(filterLog.TransactionIndex))
            .HasField(PresetSearchFieldName.log_block_hash,
                      f => f.IsString(),
                      f => f.HasFlags(),
                      f => f.ReturnsValue(filterLog.BlockHash))
            .HasField(PresetSearchFieldName.log_block_number,
                      f => f.IsHexBigInteger(),
                      f => f.HasFlags(isFilterable: true, isSearchable: true, isSortable: true, isFacetable: true),
                      f => f.ReturnsValue(filterLog.BlockNumber))
            .HasField(PresetSearchFieldName.log_address,
                      f => f.IsString(),
                      f => f.HasFlags(isFilterable: true, isSearchable: true, isSortable: true, isFacetable: true),
                      f => f.ReturnsValue(filterLog.Address))
            .HasField(PresetSearchFieldName.log_topics,
                      f => f.IsString(),
                      f => f.HasFlags(isFilterable: true, isSearchable: true, isFacetable: true, isCollection: true),
                      f => f.ReturnsValue(filterLog.Topics));
        }
예제 #16
0
        public void StaticPropertiesOnDtoAreIgnored()
        {
            var searchIndex = new EventIndexDefinition <TransferEvent_Custom>(addPresetEventLogFields: false);

            Assert.Null(searchIndex.Field("Metadata.CurrentChainUrl"));
        }
예제 #17
0
        public void WillProvideDefaultPropertyName()
        {
            var searchIndex = new EventIndexDefinition <CustomEventDtoD>();

            Assert.NotNull(searchIndex.Field("Sender"));
        }
예제 #18
0
        public void WillExcludeIgnoredFields()
        {
            var searchIndex = new EventIndexDefinition <CustomEventDtoC>();

            Assert.Null(searchIndex.Field("Sender"));
        }
예제 #19
0
        public async Task <IAzureEventSearchIndex <TEvent> > GetOrCreateIndex <TEvent>(EventIndexDefinition <TEvent> searchIndexDefinition) where TEvent : class
        {
            var azureIndex = await GetOrCreateAzureIndex(searchIndexDefinition);

            return(new AzureEventSearchSearchIndex <TEvent>(searchIndexDefinition, azureIndex, _client.Indexes.GetClient(azureIndex.Name)));
        }
예제 #20
0
 public static GenericSearchDocument ToAzureDocument <TEvent>(
     this EventLog <TEvent> log,
     EventIndexDefinition <TEvent> indexDefinition) where TEvent : class
 {
     return(CreateFieldWithValueDictionary(log, indexDefinition.Fields, (field) => field.GetEventLogValue(log)));
 }
예제 #21
0
 public AzureEventSearchSearchIndex(EventIndexDefinition <TEvent> eventSearchDefinition, Index index, ISearchIndexClient indexClient)
     : base(index, indexClient)
 {
     _eventSearchDefinition = eventSearchDefinition;
 }
        public async Task <IEventIndexer <TEvent> > CreateEventIndexer <TEvent>(EventIndexDefinition <TEvent> searchIndexDefinition) where TEvent : class
        {
            var azureIndex = await GetOrCreateAzureIndex(searchIndexDefinition);

            return(new AzureEventIndexer <TEvent>(searchIndexDefinition, azureIndex, GetOrCreateIndexClient(azureIndex.Name)));
        }
예제 #23
0
        public void IndexNameCanBeOverridden()
        {
            var searchIndex = new EventIndexDefinition <CustomEventDtoA>();

            Assert.Equal("IndexA", searchIndex.IndexName);
        }