ElasticSearch NEST recreate index with zero downtime - elasticsearch

I am writing backend in C# for a website. I'd like to recreate index with little downtime.
After reading these two posts:
Nest Client c# 7.0 for elastic search removing Aliases
Recreate ElasticSearch Index with Nest 7.x
I come up with this:
var alias_exist = await _client.Indices.ExistsAsync(index_string_alias);
if (alias_exist.Exists)
{
var oldIndices = await _client.GetIndicesPointingToAliasAsync(index_string_alias);
var oldIndexName = oldIndices.First().ToString();
await _client.Indices.BulkAliasAsync(new BulkAliasRequest
{
Actions = new List<IAliasAction>
{
new AliasRemoveAction {Remove = new AliasRemoveOperation {Index = oldIndexName, Alias = index_string_alias}},
new AliasAddAction {Add = new AliasAddOperation {Index = index_string_unique, Alias = index_string_alias}}
}
});
} else
{
var putAliasResponse = await _client.Indices.PutAliasAsync(new PutAliasRequest(index_string_unique, index_string_alias));
}
}
I'd like to remove index_string_alias if exists and assign the alias to the newly created index_string_unique.
Also, I'd like to confirm that I can treat the alias as the index name in my other queries.
I am really new to Elastic Search and wonder how people figure out these things. I searched through the official documentation and found little information about the async functions in NEST. Where should I look for explanations for functions?

Related

What is a replacement for AnalyzeAsync in NEST 7.x?

I update my app from Nest version 6.8 to 7.3, and found, that AnalyzeAsync method currently not supported. What is a replacement for the following code?
var analyzeRequest = new AnalyzeRequest(_elasticSearchSettings.PatentFamilyIndexName)
{
Analyzer = analyzer,
Text = new[] {wordsList}
};
var analyzeResponse = await ElasticClient.AnalyzeAsync(analyzeRequest)
With NEST 7.x, API methods have been grouped under the area of functionality that thery're related to
var client = new ElasticClient();
var analyzeRequest = new AnalyzeRequest(_elasticSearchSettings.PatentFamilyIndexName)
{
Analyzer = analyzer,
Text = new[] { wordsList }
};
var analyzeResponse = await client.Indices.AnalyzeAsync(analyzeRequest);
This aligns NEST with the grouping in the REST API specs, as well as other clients. You can read more about the changes in the 7.x release blog post.

Mock Elastic Search response in.Net

I have Elastic Search Nest library code and need to mock the response i am getting from elastic search index.
var obj = service.Search<TestDocument>(new student().Query());
var Name= obj.Aggs.Terms("Name");
For Testing :
I am creating the Nest object after doing quick watch but facing issue -Aggregations - is a internal protected property and i am not able to set this value.
new Nest.KeyedBucket<object>
{
Key="XYZ school",
KeyAsString=null,
Aggregations=new Dictionary<string, IAggregationContainer>{}
}
Please suggest solution or any other approach i can use to mock elastic search nest object .
If you really want to stub the response from the client, you could do something like the following with Moq
var client = new Mock<IElasticClient>();
var searchResponse = new Mock<ISearchResponse<object>>();
var aggregations = new AggregateDictionary(new Dictionary<string, IAggregate> {
["Name"] = new BucketAggregate
{
Items = new List<KeyedBucket<object>>
{
new Nest.KeyedBucket<object>(new Dictionary<string, IAggregate>())
{
Key = "XYZ school",
KeyAsString = null,
DocCount = 5
}
}.AsReadOnly()
}
});
searchResponse.Setup(s => s.Aggregations).Returns(aggregations);
client.Setup(c => c.Search<object>(It.IsAny<Func<SearchDescriptor<object>, ISearchRequest>>()))
.Returns(searchResponse.Object);
var response = client.Object.Search<object>(s => s);
var terms = response.Aggregations.Terms("Name");
Another way would be to use the InMemoryConnection and return known JSON in response to a request..
For testing purposes however, it may be better to have an instance of Elasticsearch running, and perform integration tests against it. Take a look at Elastic.Xunit which provides an easy way to spin up an Elasticsearch cluster for testing purposes. This is used by the client in integration tests.
You can get Elastic.Xunit from the Appveyor feed.

Bulk Update on ElasticSearch using NEST

I am trying to replacing the documents on ES using NEST. I am seeing the following options are available.
Option #1:
var documents = new List<dynamic>();
`var blkOperations = documents.Select(doc => new BulkIndexOperation<T>`(doc)).Cast<IBulkOperation>().ToList();
var blkRequest = new BulkRequest()
{
Refresh = true,
Index = indexName,
Type = typeName,
Consistency = Consistency.One,
Operations = blkOperations
};
var response1 = _client.Raw.BulkAsync<T>(blkRequest);
Option #2:
var descriptor = new BulkDescriptor();
foreach (var eachDoc in document)
{
var doc = eachDoc;
descriptor.Index<T>(i => i
.Index(indexName)
.Type(typeName)
.Document(doc));
}
var response = await _client.Raw.BulkAsync<T>(descriptor);
So can anyone tell me which one is better or any other option to do bulk updates or deletes using NEST?
You are passing the bulk request to the ElasticsearchClient i.e. ElasticClient.Raw, when you should be passing it to ElasticClient.BulkAsync() or ElasticClient.Bulk() which can accept a bulk request type.
Using BulkRequest or BulkDescriptor are two different approaches that are offered by NEST for writing queries; the former uses an Object Initializer Syntax for building up a request object while the latter is used within the Fluent API to build a request using lambda expressions.
In your example, BulkDescriptor is used outside of the context of the fluent API, but both BulkRequest and BulkDescriptor implement IBulkRequest so can be passed to ElasticClient.Bulk(IBulkRequest).
As for which to use, in this case it doesn't matter so whichever you prefer.

Is there a way to get results of solr grouping using Solr Net

I want to try new solr collapsing/grouping included in solr 3.3, i have tried queries on solr Admin page and that works absolutely right but when I try to query in my c# code using solr net that does not seem to work as expected. Here is how I am setting the param values
options.ExtraParams = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string,string>("group","true"),
new KeyValuePair<string,string>("group.field","AuthorID"),
};
Yes, you can use Grouping (formerly known as Field Collapsing) with SolrNet, it was introduced in the SolrNet 0.4.0 alpha1 release. Here are the release notes on the author's blog about this support being added in. So you will need to grab that version (or later) from Google Code(binaries) or GitHub(source). Also here is an example of using grouping from the unit tests in the source - Grouping Tests
public void FieldGrouping()
{
var solr = ServiceLocator.Current.GetInstance<ISolrBasicOperations<Product>>();
var results = solr.Query(SolrQuery.All, new QueryOptions
{
Grouping = new GroupingParameters()
{
Fields = new [] { "manu_exact" },
Format = GroupingFormat.Grouped,
Limit = 1,
}
});
Console.WriteLine("Group.Count {0}", results.Grouping.Count);
Assert.AreEqual(1, results.Grouping.Count);
Assert.AreEqual(true, results.Grouping.ContainsKey("manu_exact"));
Assert.GreaterThanOrEqualTo(results.Grouping["manu_exact"].Groups.Count,1);
}

Lucene.NET - sorting by int

In the latest version of Lucene (or Lucene.NET), what is the proper way to get the search results back in sorted order?
I have a document like this:
var document = new Lucene.Document();
document.AddField("Text", "foobar");
document.AddField("CreationDate", DateTime.Now.Ticks.ToString()); // store the date as an int
indexWriter.AddDocument(document);
Now I want do a search and get my results back in order of most recent.
How can I do a search that orders results by CreationDate? All the documentation I see is for old Lucene versions that use now-deprecated APIs.
After doing some research and poking around with the API, I've finally found some non-deprecated APIs (as of v2.9 and v3.0) that will allow you to order by date:
// Find all docs whose .Text contains "hello", ordered by .CreationDate.
var query = new QueryParser(Lucene.Net.Util.Version.LUCENE_29, "Text", new StandardAnalyzer()).Parse("hello");
var indexDirectory = FSDirectory.Open(new DirectoryInfo("c:\\foo"));
var searcher = new IndexSearcher(indexDirectory, true);
try
{
var sort = new Sort(new SortField("CreationDate", SortField.LONG));
var filter = new QueryWrapperFilter(query);
var results = searcher.Search(query, , 1000, sort);
foreach (var hit in results.scoreDocs)
{
Document document = searcher.Doc(hit.doc);
Console.WriteLine("\tFound match: {0}", document.Get("Text"));
}
}
finally
{
searcher.Close();
}
Note I'm sorting the creation date with the LONG comparison. That's because I store the creation date as DateTime.Now.Ticks, which is a System.Int64, or long in C#.

Resources