paging over all ingested docs in elastic search - c#

I am trying to use primitive code like this:
var pageSize = 100;
var startPosition = 0;
do
{
var searchResponse = client.Search<Bla>(s => s
.Index(indexName)
.Query(q => q.MatchAll()
).From(startPosition).Size(pageSize)
);
startPosition = startPosition + pageSize;
} while (true);
to page over all ingested documents. This breaks the server as the requests are too frequent I believe. I could slow things down by going to sleep for a few milliseconds, but I think this would still not be best practice.
I know there is also the concept of scrolling. How would I use this in my scenario, where I would like to act upon each page's result?
PS:
static void Main(string[] args)
{
var indexName = "document";
var client = GetClient(indexName);
var pageSize = 1000;
var numberOfSlices = 4;
var scrollObserver = client.ScrollAll<Document>("1m", numberOfSlices, s => s
.MaxDegreeOfParallelism(numberOfSlices)
.Search(search => search
.Index(indexName).MatchAll()
.Size(pageSize)
)
).Wait(TimeSpan.FromMinutes(60), r =>
{
// do something with documents from a given response.
var documents = r.SearchResponse.Documents.ToList();
Console.WriteLine(documents[0].Id);
});
}
I am familiar with the observer pattern but not sure what exactly these components mean:
"1m"
numberOfSlices
TimeSpan.FromMinutes(60)

Something along those lines seems to work:
const string indexName = "bla";
var client = GetClient(indexName);
const int scrollTimeout = 1000;
var initialResponse = client.Search<Document>
(scr => scr.Index(indexName)
.From(0)
.Take(100)
.MatchAll()
.Scroll(scrollTimeout))
;
List<XYZ> results;
results = new List<XYZ>();
if (!initialResponse.IsValid || string.IsNullOrEmpty(initialResponse.ScrollId))
throw new Exception(initialResponse.ServerError.Error.Reason);
if (initialResponse.Documents.Any())
results.AddRange(initialResponse.Documents);
var scrollid = initialResponse.ScrollId;
bool isScrollSetHasData = true;
while (isScrollSetHasData)
{
var loopingResponse = client.Scroll<XYZ>(scrollTimeout, scrollid);
if (loopingResponse.IsValid)
{
results.AddRange(loopingResponse.Documents);
scrollid = loopingResponse.ScrollId;
}
isScrollSetHasData = loopingResponse.Documents.Any();
// do some amazing stuff
}
client.ClearScroll(new ClearScrollRequest(scrollid));

Related

How to match list of areas to a "address"(string) and get the area which is present in both list and string Asp.net core

Hello every one i have string containing Address and list of Areas from Db, i want to get the area from address string which is present in both list of areas and address string.how can i do this without looping because through looping it will take to much time. Any solution please through regular expression or any other approach.
var data = _context.OrderDetails.Where(c => c.ConsignmentId == cId)
.Select(c => new {address = c.DeliveryAddress, cityId = c.CityId}).ToList();
string EncryptedConsId = _customEncryptionDecryption.Encode(cId);
Regex re = new Regex(#"^(.*?(\bkarachi\b)[^$]*)$");
MatchCollection cityA = re.Matches(data[0].address.ToLower());
if (cityA.Count != 0)
{
var cityNameA = cityA[0].Groups[2];
if (cityNameA.Value == "karachi")
{
var areasForCityA = _context.Areas.Where(a => a.CityId == 1).ToList();
}
}
i have solve my problm by doing this,Thanks to all of You Thank you so much
var areas = _context.Areas.Where(a => a.CityId == data[0].cityId).ToList();
for (int i = 0; i < areas.Count; i++)
{
var result = data[0].address.ToLower().Contains(areas[i].Title.ToLower());
if (result)
{
AreaId = areas[i].Id;
CityId = data[0].cityId;
var order = _context.OrderDetails.Where(o => o.ConsignmentId == cId).SingleOrDefault();
order.AreaId = AreaId;
_context.SaveChanges();
break;
}
}

Rewriting loop from Python to C#, what's wrong?

I'm trying to rewrite part of code from Python to C#. I even rewrote it but it returns incorrect results and I can not see an error. Can anyone say what's wrong here? It's probably some small mistake ...
Here's Python code:
maximals = maximals.groupby(maximals.index.month)['avg'].nlargest(10)
SSV = 3.8
SOP = 7.78
costs = []
power_max = np.ceil(np.sort(maximals.values)[-1])
power_safe = np.ceil(11/10 * power_max)
for contr_power in range(0,int(2*power_max)):
excess = [maximals.values[i] - contr_power for i in range(0,len(maximals.values)) if maximals.values[i] > contr_power]
cost = len(months) * (SSV+SOP) * contr_power + SSV * sum(excess)
costs.append([contr_power, cost])
costs_df = pd.DataFrame(costs, columns = ['contr_power', 'cost'])
power_optim = costs_df.sort_values(by='cost').contr_power.values[0]
And here's my C# code. In this case, variable "result" is the same as "maximals" from Python code:
var pMax = result.Max(v => v.Value);
powerAvgValues.powerMax = Math.Ceiling(pMax);
powerAvgValues.powerSafe = Math.Ceiling(1.1*pMax);
var months = result.AsEnumerable()
.GroupBy(m => new { m.Time.Month })
.Distinct()
.ToList();
var SSV = 3.8;
var SOP = 7.78;
var monthsCount = months.Count;
for (var contr_power = 0; contr_power < 2 * (int)pMax; contr_power++)
{
for (int i = 0; i < result.Count; i++)
{
if (result[i].Value > contr_power)
{
var excess = result[i].Value - contr_power;
excessList.Add(excess);
}
}
var cost = monthsCount * (SSV + SOP) * contr_power + SSV * excessList.Sum();
var itemToCosts = new Costs();
itemToCosts.contr_power = contr_power;
itemToCosts.cost = cost;
costs.Add(itemToCosts);
}
var power_optim = costs.AsEnumerable()
.OrderBy(c => c.cost)
.Min(d => d.contr_power);
powerAvgValues.powerOptim = power_optim;

Elasticsearch ScrollId returns no document

I'm facing a strange issue with Elastisearch and scroll. I'm trying to get 50 192 records from my index but scrollId is returning 0 so my loop doesn't execute. There is my code :
var results = new List<MyModelList>();
var scanResults = client.Search<MyModel>(s => s
.Index("myindex")
.Type("MyIndexType")
.From(0)
.Size(2000)
.Query(q => q.QueryString(qs => qs.Query(query)))
.Scroll("5m")
);
var resultsscroll = client.Scroll<MyModel>("10m", scanResults.ScrollId);
while (resultsscroll.Documents.Any())
{
foreach (var doc in results)
{
results.Add(doc);
}
resultsscroll = client.Scroll<MyModel>("10m", resultsscroll.ScrollId);
}
return results;
When putting a break point, I can see that scanResults is set to 2000, but next, resultsscroll is at 0. What am I doing wrong? Followed the official doc, and make some search, seems everyone is using it this way. If someone as an idea of why it is not working it would be nice.
You will see that I've removed :
.SearchType(Nest.SearchType.Scan)
From my query, because if I let it, scanResults is set to 0. Don't understand why neither.
This is how if fixes my issue (also here on Aman's demand).
//Settings
var maxQuery = 50000;
//Connection
var client = ConnectElasticClient();
//Prepare Result
var results = new List<ModelDL>();
var countHits = (int)client.Search<Model>(s => s.Index("MyIndex").Type("MyType")
.Query(q => q.QueryString(qs => qs.Query(query)))).Total;
//First Query
var response =
client.Search<Model>(s => s.Index("MyIndex").Type("MyType").Size(maxQuery)
.Query(q => q.QueryString(qs => qs.Query(query))));
if (countHits <= maxQuery)
{
return results;
}
var cpt = maxQuery;
for (var i = 0; i < ((countHits - maxQuery) / maxQuery); i++)
{
var res =
client.Search<Model>(s => s.Index("MyIndex").Type("MyType").From(cpt).Size(maxQuery)
.Query(q => q.QueryString(qs => qs.Query(query))));
cpt += maxQuery;
results.AddRange(res.Documents.Select(x => new EntrepriseSireneDL(x)));
}
var lastScrollSize = countHits - cpt;
var r =
client.Search<Model>(s => s.Index("MyIndex").Type("MyType").From(cpt).Size(lastScrollSize)
.Query(q => q.QueryString(qs => qs.Query(query))));
results.AddRange(r.Documents.Select(x => new ModelDL(x)));
return results;
This way, i get everything i want as i want it.

C# find object in list using a object field

So i have the following List:
List<AttackStyle> AttackStyles = new List<AttackStyle>();
With the following types of objects:
AttackStyle lStyle = new AttackStyle();
lStyle.Name = "Attack Achilles";
lStyle.ParameterID = 0;
lStyle.Forward = Vector3.forward;
lStyle.HorizontalFOA = 70f;
lStyle.VerticalFOA = 40f;
lStyle.DamageModifier = 1f;
lStyle.ActionStyleAlias = "Jump";
lStyle.IsInterruptible = true;
AttackStyles.Add(lStyle);
Now i wish to find the field ParameterID where the ActionStyleAlias is equal to a value (for instance "Jump")
This is for a Unity application so the search / find needs to be as fast as possible.
var result = AttackStyles.FirstOrDefault(x => x.ActionStyleAlias == "Jump").ParameterID;
The straight solution is:
var pId = AttackStyles.FirstOrDefault(x=> x.ActionStyleAlias == "Jump")?.ParameterID
But if you want to get a better performance, it would be better, to index the most useful property which you want. Therefore, construct a dictionary on the most useful fields to get a better performance in time. For example:
var styles = new Dictionary<string, AttackStyle>();
styles.Add("Jump", new AttackStyle()
{
Name = "Attack Achilles",
ParameterID = 0,
Forward = Vector3.forward,
HorizontalFOA = 70f,
VerticalFOA = 40f,
DamageModifier = 1f,
ActionStyleAlias = "Jump",
IsInterruptible = true
});
Then, find the object by this:
var pId = styles["Jump"].ParamterId;
or if it might be null:
if(styles.Keys.Contains("Jump"))
var pId = styles["Jump"].ParamterId;
var param = AttackStyles.First(x => x.ActionStyleAlias.Equals(value)).ParameterID;
Let's return first ParameterID if there's the required item in the collection; -1 otherwise:
var result = AttackStyles
.Where(item => item.ActionStyleAlias == "Jump")
.Select(item => item.ParameterID)
.DefaultIfEmpty(-1)
.First();
You can try extension methods. Also you should consider null cases:
static class Extensions
{
public static int? FindParameterId(this List<AttackStyle> values, string actionStyleAlias)
{
return values.FirstOrDefault(x => x.ActionStyleAlias == actionStyleAlias)?.ParameterID;
}
}
Then use it:
List<AttackStyle> attackStyles = new List<AttackStyle>();
var parameterId = attackStyles.FindParameterId("Jump");

Getting max volgnr in nested object graph

I have following code :
void Main()
{
Order order = new Order
{
Catalogen = new List<Catalog>
{
new Catalog
{
Artikels = new List<Artikel>
{
new Artikel{PosNr=1}, new Artikel{PosNr=2}, new Artikel{PosNr=3}
}
},
new Catalog
{
Artikels = new List<Artikel>
{
new Artikel{PosNr=1}, new Artikel{PosNr=2}, new Artikel{PosNr=6}
}
}
}
};
int max=1;
try
{
max = order.Catalogen
.Where(c => c.Artikels.Count > 0)
.Max(c => c.Artikels.Max(a => a.PosNr)) + 1;
}
catch(Exception Ex)
{
max = 1;
}
Console.WriteLine (max);
}
class Artikel {
public int PosNr;
};
class Catalog {
public List<Artikel> Artikels;
};
class Order {
public List<Catalog> Catalogen;
}
Is there a more simple way to get the max posnr taking into account that an ordercatalog can be empty ? The where seems to be needed to consider this fact but it makes the code look clunchy so I am looking for a better way.
var q = from cataloog in order.Catalogen
from artikel in cataloog.Artikels
select artikel.Posnr;
var max = q.Max() + 1;
Alternatively
var max = order.Catalogen.SelectMany(c => c.Artikels).Max(a => a.Posnr) + 1;
Update:
Of course, if there are no Artikels, than the maximum Posnr is undefined, which is reported by Enumerable.Max as an InvalidOperationException.
In your specific case, there is an easy solution for that:
var max = order.Catalogen.SelectMany(c => c.Artikels)
.Select(a => a.Posnr)
.DefaultIfEmpty()
.Max() + 1;

Categories

Resources