JD2022-TU1/main/tools/framework/JD.ElasticSearch/ElasticSearchClient.cs

162 lines
5.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using Elasticsearch.Net;
using Nest;
using Newtonsoft.Json;
namespace JD.ElasticSearch
{
public class ElasticSearchClient
{
public class ElasticClientInstance
{
public ElasticClient Client {get; set;}
public string[] Uri {get; set;}
public string UserName { get; set; }
public string Password { get; set; }
public ElasticClientInstance(ElasticClient client, string[] uri, string userName , string password)
{
Client = client;
Uri = uri;
UserName = userName;
Password = password;
}
public HttpStatusCode PutDocument(string index, string type, string id, object document)
{
try
{
string json = JsonConvert.SerializeObject(document);
var indexResponse = Client.LowLevel.Index<StringResponse>(index, type, id, json);
var code = (HttpStatusCode)indexResponse.HttpStatusCode.GetValueOrDefault((int)HttpStatusCode.ServiceUnavailable);
return code;
}
catch (Exception)
{
return HttpStatusCode.ServiceUnavailable;
}
}
/// <summary>
/// Search for statistics matching the specified <paramref name="query"/>
/// </summary>
/// <param name="index"></param>
/// <param name="query">Specify the search filter here</param>
/// <param name="size">Number of rows returned</param>
/// <param name="debug">Keeps additional information to help debugging but is less efficient.</param>
/// <remarks>
/// See how to write queries on NEST help:
/// https://www.elastic.co/guide/en/elasticsearch/client/net-api/1.x/writing-queries.html
/// </remarks>
public IEnumerable<T> Search<T>(string index, QueryContainer query = null, int size = 1000, bool debug = false)
where T : class
{
var request = new SearchRequest(index + "*", typeof(T).Name)
{
From = 0,
Size = size,
Sort = new List<ISort> { new SortField { Field = "DateTime", Order = SortOrder.Descending, UnmappedType = FieldType.Boolean } },
Query = query,
};
var result = Client.Search<T>(request);
if (debug)
{
Trace.WriteLine($"{result.DebugInformation}");
}
return result.Hits.Select(x => x.Source);
}
public bool IsEquivalentClient(string[] connectionNodes, string userName, string password)
{
if(!Enumerable.SequenceEqual(connectionNodes, Uri))
{
return false;
}
if(!UserName.Equals(userName))
{
return false;
}
if(!Password.Equals(password))
{
return false;
}
return true;
}
}
//private static uint maxClients = 5;
private static List<ElasticClientInstance> _clients = new List<ElasticClientInstance>();
private ElasticClientInstance clientInstance;
public ElasticSearchClient(string[] connectionNodes, string userName = "", string password = "", string defaultIndex = "*")
{
clientInstance = CreateHighLevelClient(connectionNodes, userName, password, defaultIndex);
}
public HttpStatusCode PutDocument(string index, string type, string id, object document)
{
return clientInstance.PutDocument(index, type, id, document);
}
public IEnumerable<T> Search<T>(string index, QueryContainer query = null, int size = 1000, bool debug = false)
where T : class
{
return clientInstance.Search<T>(index, query, size, debug);
}
/// <summary>
/// See how to connect to elastic on:
/// http://nest.azurewebsites.net/elasticsearch-net/connecting.html
/// </summary>
public static ElasticClientInstance CreateHighLevelClient(string[] connectionNodes, string userName, string password, string defaultIndex, bool debug = false)
{
for (int i = 0; i < _clients.Count; ++i)
{
if (_clients[i].IsEquivalentClient(connectionNodes, userName, password))
{
return _clients[i];
}
}
var nodesUri = connectionNodes.Select(x => new Uri(x));
// Using a connection pool allows to "round robin" on the different nodes
var connectionPool = new StaticConnectionPool(nodesUri);
var config = new ConnectionSettings(connectionPool);
config.BasicAuthentication(userName, password);
config.RequestTimeout(TimeSpan.FromSeconds(10));
config.DefaultIndex(defaultIndex);
if (debug)
{
// This allows to inspect the queries results.
config.DisableDirectStreaming();
}
var elasticClient = new ElasticClient(config);
var newClient = new ElasticClientInstance(elasticClient, connectionNodes, userName, password);
_clients.Add(newClient);
return newClient;
}
}
}