ElasticSearch documentation is far from decent, so I ask here after reading them.
I've put up the easiest elasticsearch example after looking at their horrific documentation.
I got local elasticsearch client (starts on localhost:9200) and NEST library to try and put up a simple console program that indexes some files and try to search them by name.
Can someone help me and tell me why I don't find any result?
using Nest;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ElasticHorror
{
class Program
{
static void Main(string[] args)
{
Uri connectionString = new Uri("http://localhost:9200");
//Client settings, index must be lowercase
var settings = new ConnectionSettings(connectionString).DefaultIndex("tests");
settings.PrettyJson();
settings.ThrowExceptions();
//Client initialization
var client = new ElasticClient(settings);
//Index creation, I use a forced bool for testing in a console program only ;)
bool firstRun = true;
if (firstRun)
{
foreach(string file in Directory.GetFiles(#"G:\SomeFolderWithFiles", "*.*", SearchOption.AllDirectories))
{
Console.WriteLine($"Indexing document {file}");
client.IndexDocument<FileProps>(new FileProps(new FileInfo(file)));
}
}
var searchResponse = client.Search<FileProps>(s => s.Query(
doc => doc.Term(t => t.Name, "Test")))
.Documents;
}
internal class FileProps
{
public FileProps(FileInfo x)
{
CreationTime = x.CreationTime;
Extension = x.Extension;
FullName = x.FullName;
Lenght = x.Length;
Name = x.Name;
Directory = x.DirectoryName;
}
[Date]
public DateTime CreationTime { get; private set; }
public string Extension { get; private set; }
public string FullName { get; private set; }
public long Lenght { get; private set; }
public string Name;
public string Directory;
}
}
}
Thanks
Simple Example For You
Model
internal class Person
{
public int id { get; set; }
public string firstname { get; set; }
public string lastname { get; set; }
public string Mnumber { get; set; }
public string Email { get; set; }
}
var settings = new ConnectionSettings(new Uri("http://localhost:9200"));
settings.DefaultIndex("bar");
var client = new ElasticClient(settings);
var person = new Person
{
id = 2,
firstname = "Martijn123Hitesh",
lastname = "Martijn123",
Mnumber="97224261678",
Email="hitesh#gmail.com"
};
var indexedResult = client.Index(person, i => i.Index("bar"));
var searchResponse = client.Search<Person>(s => s
.Index("bar")
.Query(q => q
.Match(m => m
.Field(f => f.firstname)
.Query("Martijn123Hitesh")
)
)
);
Like Query in Elastic search Example
var searchResponseww = client.Search<Person>(s => s
.Index("bar")
.Query(q => q
.Bool(b => b
.Should(m => m
.Wildcard(c => c
.Field("firstname").Value("Martijn123".ToLower() + "*")
)))));
Related
I'm sorry that I interrupt you in this manner, I'm new to C# and I've been struggling with this problem for days... Maybe it will seem easy for you :)
I have this text file in this format
name|ID|domain|grade|verdict
Ryan|502322|Computers|9,33|Undefined
Marcel|302112|Automatics|6,22|Undefined
Alex|301234|Computers|5,66|Undefined
Leo|201122|Automatics|3,22|Undefined
How can I sort the text file using any methods (including LINQ) so that the list from the text file will be ordered by domain, and then descending by the grade column? Like this:
name|ID|domain|grade|verdict
Marcel|302112|Automatics|6,22|Undefined
Leo|201122|Automatics|3,22|Undefined
Ryan|502322|Computers|9,33|Undefined
Alex|301234|Computers|5,66|Undefined
To read the file, I'm using var Students = File.ReadAllLines(#"filepath");, I don't know if it's the smartest approach, and then I write using File.WriteAllLines
Thanks in advance! Sorry once again, I know it should be easy, but for me is really tuff :(
You can use some thing like this:
var students= File.ReadAllLines(#"filepath");
var headers = lines[0];
students = lines.Skip(1).ToArray();
var orders = lines.Select(x => x.Split('|'))
.Select(x => new { Domain = x[2], Grade = int.Parse(x[3].Replace(",", "")), All = x })
.OrderBy(x => x.Domain).ThenByDescending(x => x.Grade).Select(x => string.Join("|", x.All)).ToList();
orders.Insert(0, headers);
students=orders.ToArray();
try following code:
private void ReadFile()
{
char Delimiter = '|';
string[] Lines = File.ReadAllLines(#"E:\RaftehHa.txt", Encoding.Default);
List<string[]> FileRows = Lines.Select(line =>
line.Split(new[] { Delimiter }, StringSplitOptions.RemoveEmptyEntries)).ToList();
DataTable dt = new DataTable();
dt.Columns.AddRange(FileRows[0].Select(col => new DataColumn() { ColumnName = col }).ToArray());
FileRows.RemoveAt(0);
FileRows.ForEach(row => dt.Rows.Add(row));
DataView dv = dt.DefaultView;
dv.Sort = " ID ASC ";
dt = dv.ToTable();
dataGridView1.DataSource = dt;
}
A bit the same as already mentioned above, but as you mention you are new to C#, I have tried to add a little bit of structure to the code, but leaving the completion to you.
public class Data
{
public Data(string inputLine)
{
var split = inputLine.Split('|');
Name = split[0];
Id = int.Parse(split[1]);
Domain = split[2];
Grade = double.Parse(split[3].Replace(",", "."));
Verdict = split[4];
}
public string Name { get; }
public int Id { get; }
public string Domain { get; }
public double Grade { get; }
public string Verdict { get; }
}
public class DataFile
{
public static IEnumerable Read(string fileName)
{
var input = File.ReadAllLines(fileName);
return input.Skip(1).Select(p => new Data(p)); // skip header
}
public static void Write(IEnumerable data)
{
// todo :)
}
}
void Main()
{
var input = DataFile.Read(#"C:\Temp\ExampleData.txt");
var result = input.OrderBy(p => p.Domain).ThenByDescending(p => p.Grade);
DataFile.Write(result);
}
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
enum DomainType {
Automatics, // 0
Computers // 1
}
class Data {
public int Id { get; set; }
public string Name { get; set; }
public string Verdict { get; set; }
public DomainType Domain { get; set; }
public Tuple<int, int> Grade { get; set; }
}
public static class Program {
static IEnumerable<Data> FileContent(string path) {
string line;
using (var reader = File.OpenText(path))
{
bool skipHeader = false;
while((line = reader.ReadLine()) != null)
{
if (!skipHeader) {
skipHeader = true;
continue;
}
var fields = line.Split('|');
string name = fields[0];
int id = int.Parse(fields[1]);
var domain = (DomainType)Enum.Parse(typeof(DomainType), fields[2]);
var grade = Tuple.Create(int.Parse(fields[3].Split(',')[0]),
int.Parse(fields[3].Split(',')[1]));
string verdict = fields[4];
var data = new Data() {
Name = name, Id = id, Domain = domain, Grade = grade, Verdict = verdict };
yield return data;
}
}
}
public static void Main() {
var result = FileContent("path_to_file").OrderBy(data => data.Domain);
foreach (var line in result) {
Console.WriteLine(line.Name);
}
}
}
Program.cs
using ConsoleApp2.Models;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
string City_Name = "GdaĆsk";
var doc = XElement.Load($"https://maps.googleapis.com/maps/api/place/textsearch/xml?key={key}&query=restaurants+in+{City_Name}&language=pl&fields=place_id");
List<PlaceIdModel> IdList = doc.Descendants("result").Select(n => new PlaceIdModel
{
PlaceId = n.Element("place_id").Value
}).ToList();
List<PlaceDetailsModel> placeDetailsModel = new List<PlaceDetailsModel>();
foreach (var item in IdList)
{
var doc2 = XElement.Load($"https://maps.googleapis.com/maps/api/place/details/xml?key={key}&place_id={item.PlaceId}&language=pl&fields=name,vicinity,geometry/location,rating,website,opening_hours/weekday_text");
placeDetailsModel = doc2.Descendants("result").Select(x => new PlaceDetailsModel
{
Name = x.Element("name").Value,
Vicinity = x.Element("vicinity").Value,
Rating = x.Element("rating").Value,
Website = x.Element("website").Value,
Lat = x.Element("geometry").Element("location").Element("lat").Value,
Lng = x.Element("geometry").Element("location").Element("lng").Value,
Opening_hours = x.Descendants("weekday_text").Select(y => y.Value).ToList()
}).ToList();
};
}
}
}
PlaceIdModel.cs
namespace ConsoleApp2.Models
{
public class PlaceIdModel
{
public string PlaceId { get; set; }
}
}
PlaceDetailsModel.cs
using System.Collections.Generic;
namespace ConsoleApp2.Models
{
public class PlaceDetailsModel
{
public string Name { get; set; }
public string Vicinity { get; set; }
public string Rating { get; set; }
public string Website { get; set; }
public string Lat { get; set; }
public string Lng { get; set; }
public List<string> Opening_hours { get; set; }
}
}
I'm using goole API places. First I get place_id from city then I want to use loop foreach to save details of every place into list. Everytime everything save on [0] instead populate whole list.
With .ToList() you are creating a new list every time. Instead add the items to the existing list with the List.AddRange(IEnumerable) Method.
var placeDetailsModel = new List<PlaceDetailsModel>();
foreach (var item in IdList)
{
var doc2 = XElement.Load($"https://maps.googleapis.com/maps/...");
placeDetailsModel.AddRange(
doc2.Descendants("result")
.Select(x => new PlaceDetailsModel
{
Name = x.Element("name").Value,
Vicinity = x.Element("vicinity").Value,
Rating = x.Element("rating").Value,
Website = x.Element("website").Value,
Lat = x.Element("geometry").Element("location").Element("lat").Value,
Lng = x.Element("geometry").Element("location").Element("lng").Value,
Opening_hours = x.Descendants("weekday_text").Select(y => y.Value).ToList()
})
);
}
You do not need the .ToList() when reading the IdList. The foreach works well with an IEnumerable<T> and it saves you an unnecessary memory allocation.:
IEnumerable<PlaceIdModel> IdList = doc
.Descendants("result")
.Select(n => new PlaceIdModel
{
PlaceId = n.Element("place_id").Value
});
...
foreach (var item in IdList) ...
I also do not see the advantage of having a PlaceIdModel class just to store the Id temporarily. Just use the values directly:
var IdList = doc
.Descendants("result")
.Select(n => n.Element("place_id").Value);
...
foreach (var id in IdList) {
var doc2 = XElement.Load($"https://maps.googleapis.com/...&place_id={id}&language=...");
...
}
I have a CSV File with Raw Data which I'm trying to match with multiple files, while sorting I need to match account codes to their accounts.
I'm using a List of Account and using StartsWith to try and match:
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var accounts = new List<Account> {
new Account {
Id = 9,
Code = "5-4",
Name = "Software",
},
new Account {
Id = 10,
Code = "5-4010",
Name = "Hardware"
}
};
var hardwareAccount = accounts.FirstOrDefault(x => "5-4010".StartsWith(x.Code));
Console.WriteLine(hardwareAccount.Name); // Prints Software - Should be Hardware
var softwareAccount = accounts.FirstOrDefault(x => "5-4020".StartsWith(x.Code));
Console.WriteLine(softwareAccount.Name); // Prints Software - Correct
}
}
public class Account {
public int Id { get; set; }
public string Code { get; set; }
public string Name { get; set; }
}
They are obviously matching the first Account, is there a way to make it match in order?
Updated Solution:
Thanks #SirRufo
class Program
{
static void Main(string[] args)
{
var accounts = new List<Account>
{
new Account
{
Id = 9,
Code = "5-4",
Name = "Software",
},
new Account
{
Id = 10,
Code = "5-4010",
Name = "Hardware"
}
}.OrderBy(x => x.Code.Length);
var hardwareAccount = accounts.LastOrDefault(x => "5-4010".StartsWith(x.Code));
Console.WriteLine(hardwareAccount.Name);
var softwareAccount = accounts.LastOrDefault(x => "5-4020".StartsWith(x.Code));
Console.WriteLine(softwareAccount.Name);
Console.ReadKey();
}
}
public class Account
{
public int Id { get; set; }
public string Code { get; set; }
public string Name { get; set; }
}
You have to order all matches by the code length
accounts
.Where(x => "5-4010".StartsWith(x.Code))
.OrderBy(x => x.Code.Length)
.LastOrDefault();
How can I specify the index name using attribute using NEST for ElasticSearch?
Here is the POCO class I used:
[Serializable]
[ElasticsearchType(IdProperty = "msgid")]
public class Message
{
[PropertyName("msgid")]
public string Id { get; set; }
[PropertyName("date")]
public string Date { get; set; }
}
You can't specify the index name(s) for a specific POCO type using attributes. You can however specify it on ConnectionSettings using .DefaultMappingFor<T>, where T is your POCO type.
When using BulkAll, you can specify an index name per bulk operation using BufferToBulk(...)
private static void Main()
{
var defaultIndex = "my-index";
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var settings = new ConnectionSettings(pool)
.DefaultIndex(defaultIndex);
var client = new ElasticClient(settings);
var bulkAll = client.BulkAll(MyDocuments(), b => b
.Index(null)
.Type(null)
.BufferToBulk((bu, docs) =>
{
foreach (var doc in docs)
{
bu.Index<MyDocument>(bi => bi
.Index(doc.Id % 2 == 0 ? "even-index" : "odd-index")
.Document(doc)
);
}
})
.RefreshOnCompleted()
.Size(100)
);
bulkAll.Wait(TimeSpan.FromMinutes(20), _ => {});
}
private static IEnumerable<MyDocument> MyDocuments()
{
for (int i = 0; i < 1000; i++)
yield return new MyDocument(i);
}
public class MyDocument
{
public MyDocument(int id)
{
Id = id;
Message = $"message {id}";
}
public int Id { get; set; }
public string Message { get; set; }
}
using (database db = new database())
{
var query = (
from c in db.tblBlogs
join a in db.tblBlogMedias on c.id equals a.BlogId
select new
{
c.id,
c.CreatedDate,
c.Author,
c.BlogTitle,
c.BlogDescription,
a.BlogId,
a.BlogPicturePath
}).OrderByDescending(d => d.id).ToList();
System.Text.StringBuilder sb = new System.Text.StringBuilder();
query.ToList().ForEach(x =>
{
sb.Append(string.Format("<div class='col-sm-4
wow fadeInUp animated' data-wow-duration='1000ms' data-wow-delay='400ms'
style='visibility: visible; animation-duration: 1000ms; animation-delay:
400ms; animation-name: fadeInUp;'><div class='post-thumb'><div class='post-
meta'>"+
"</div>"+
"</div>"+
"<div class='entry-
header'><h3><a href='#'>{0}</a></h3><span class='date'>{1}</span></div>
</div>",x.BlogTitle,x.CreatedDate));
});
}
How do I write this sql query in var query = :
select tblBlog.*,tblBlogMedia.BlogPicturePath from tblBlog left outer join
tblBlogMedia on tblBlog.id = tblBlogMedia.BlogId
where tblBlogMedia.id=(select max(id) from tblBlogMedia where BlogId='2')
With properly named entities and Navigation properties, it would look like this:
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EfDbFirstTest
{
public class Blog
{
public int Id { get; set; }
public DateTime CreatedDate { get; set; }
public string Author { get; set; }
public string BlogTitle { get; set; }
public string BlogDescription { get; set; }
public ICollection<BlogMedia> BlogMedia { get; set; }
}
public class BlogMedia
{
public int Id { get; set; }
public int BlogId { get; set; }
public Blog Blog { get; set; }
public string BlogPicturePath { get; set; }
}
public class Db : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<BlogMedia> BlogMedia { get; set; }
}
class Program
{
static void Main(string[] args)
{
using (var db = new Db())
{
db.Database.Log = m => Console.WriteLine(m);
var q = from b in db.Blogs
select new
{
b.Id,
b.CreatedDate,
b.Author,
b.BlogTitle,
b.BlogDescription,
BlogPicturePath = b.BlogMedia.Any() ? b.BlogMedia.OrderByDescending(m => m.Id).FirstOrDefault().BlogPicturePath : null
};
var results = q.ToList();
Console.ReadKey();
}
}
}
}
This is how it works perfectly as i want, I write this code in ForEach loop body and then pass the value of q in sb.append :
var q = (from d in db.tblBlogMedias
join c in db.tblBlogs on d.BlogId equals x.id
select new
{
d.Id,
d.BlogPicturePath
}).OrderByDescending(d=>d.Id).Max(d => d.BlogPicturePath);