I am working on parsing logs(Json format) in Scala. I don't know how to proceed. I may get different kinds of logs to be processed.
how do i write/design my code to handle different types of Json structures?
can i give my Scala program a schema and let it parse?
I wrote some code using Object mapper and read through the nodes but i want a more structure agnostic approach.
I am not sure where to start. please point me to some reading or examples. i tried to google or search in Stackoverflow resulting in too many examples and it is confusing as i am learning Scala also.
import org.apache.hadoop.fs.FileSystem
import org.apache.hadoop.fs.Path
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Calendar;
import org.apache.spark.sql.hive.HiveContext
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import org.apache.spark.rdd.RDD;
sc.setLogLevel("OFF");
val args = sc.getConf.get("spark.driver.args").split("\\s+")
args.foreach(println);
var envStr = "dev";
var srcStr = "appm"
val RootFolderStr = "/source_folder/";
val DestFolderStr = "/dest_folder/";
val dateformatter = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSS'Z'");
val formatter = new SimpleDateFormat("yyyy-MM-dd");
val theMonthFormatter = new SimpleDateFormat("yyyy-MM");
var fromDay: Date = formatter.parse("2018-04-29");
var toDay: Date = formatter.parse("2018-05-01");
if (args.length < 2) {
printf("usage: need at least 2 parameters in spark.driver.args");
sys.exit(2);
}
envStr = args(0).toLowerCase();
srcStr = args(1).toLowerCase();
if (args.length == 4) {
fromDay = formatter.parse(args(2));
toDay = formatter.parse(args(3));
}
if (args.length == 2) {
// default to be yesterday to today
toDay = formatter.parse(formatter.format(Calendar.getInstance().getTime()));
val previousDay = Calendar.getInstance();
previousDay.add(Calendar.DATE, -1);
fromDay = formatter.parse(formatter.format(previousDay.getTime()));
}
// get the sub-folder for the monthly partition
val monthFolder = theMonthFormatter.format(fromDay);
var rootFolder = RootFolderStr.replaceAll("ENV", envStr) + monthFolder;
rootFolder = rootFolder.replaceAll("SRC", srcStr);
val destFolder = DestFolderStr.replaceAll("ENV", envStr);
var toCalendar = Calendar.getInstance();
toCalendar.setTime(toDay);
toCalendar.add(Calendar.DATE, 1);
// need to consider the case across the month boundary
val toDay2 = formatter.parse(formatter.format(toCalendar.getTime()));
// filter out .tmp files and 0-size files
// .tmp files are not safe to read from, it's possible that the files are under updating by Flume job and the message data is incomplete
// when the Spark job starts to read from it.
val pathInfos = FileSystem.get(sc.hadoopConfiguration).listStatus(new Path(rootFolder));
// filter out the 0-length files, .tmp files which is of today
val allfiles = pathInfos.filter(fileStatus => {
if (fileStatus.getLen == 0)
false
else {
val aPath = fileStatus.getPath().getName();
// use the modification time is more accurate.
val lastTime = fileStatus.getModificationTime();
val aDate = new Date(lastTime);
// all files between fromDay and toDay2
aDate.after(fromDay) && aDate.before(toDay2);
}
}
).map(_.getPath.toString);
case class event_log(
time_stp: Long,
msg_sze: Int,
msg_src: String,
action_path: String,
s_code: Int,
s_desc: String,
p_code: String,
c_id: String,
m_id: String,
c_ip: String,
c_gp: String,
gip: String,
ggip: String,
rbody: String
);
def readEvents(fileList: Array[String], msgSrc: String, fromTS: Long, toTS: Long): RDD[(event_log)] = {
val records =
sc.sequenceFile[Long, String](fileList.mkString(","))
.filter((message) => {
(message._1 >= fromTS && message._1 < toTS);
}
)
val eventLogs = records.map((message) => {
val time_stp = message._1;
var msg_sze = message._2.length();
var c_id = ""
var m_id = "";
var p_code = "";
var c_ip = "";
var c_gp = "";
var gip = "";
var ggip = "";
var rbody = "";
var action_path = "";
var s_code: Int = 200;
var s_desc = "";
try {
// parse the message
val mapper = new ObjectMapper();
val aBuff = message._2.getBytes();
val root = mapper.readTree(aBuff);
var aNode = root.path("rbody");
rbody = aNode.textValue();
if (rbody != null && rbody.length() > 0) {
val mapper_2 = new ObjectMapper();
val aBuff_2 = rbody.getBytes();
var root2 = mapper_2.readTree(aBuff_2);
aNode = root2.path("p_code");
if (aNode != null && aNode.isValueNode())
p_code = String.valueOf(aNode.intValue());
aNode = root2.path("mkay");
if (aNode != null && aNode.isObject()) {
root2 = aNode;
}
{
aNode = root2.get("c_id");
if (aNode != null && aNode.isValueNode())
c_id = aNode.textValue();
aNode = root2.get("m_id");
if (aNode != null && aNode.isValueNode()) {
m_id = String.valueOf(aNode.intValue());
}
}
}
aNode = root.path("c_ip");
c_ip = aNode.textValue();
aNode = root.path("c_gp");
c_gp = aNode.textValue();
aNode = root.path("gip");
gip = aNode.textValue();
aNode = root.path("ggip");
ggip = aNode.textValue();
aNode = root.path("action_path");
action_path = aNode.textValue();
aNode = root.path("s_code");
val statusNodeValue = aNode.textValue().trim();
s_code = Integer.valueOf(statusNodeValue.substring(0, 3));
s_desc = statusNodeValue.substring(3).trim();
}
catch {
// return empty string as indicator that it's not a well-formatted JSON message
case jex: JsonParseException => {
msg_sze = 0
};
case ioEx: java.io.IOException => {
msg_sze = 0
};
case rtEx: JsonMappingException => {
msg_sze = 0
};
}
event_log(time_stp, msg_sze, msgSrc, action_path, s_code, s_desc,
p_code, c_id, m_id,
c_ip, c_gp, gip, ggip,
rbody);
});
eventLogs;
}
val hiveContext = new HiveContext(sc)
if (allfiles.length == 0)
sys.exit(3);
val fromTime = fromDay.getTime();
val toTime = toDay.getTime();
val events = readEvents(allfiles, srcStr, fromTime, toTime);
val df = hiveContext.createDataFrame(events).coalesce(1);
df.write.parquet(destFolder);
sys.exit(0);
Related
I have this working script to sent mails with data from a Google sheet:
function SendEmail() {
let timestamp = 0
let poid = 1
let sku = 2
let qty = 3
let description = 4
let licenseid = 5
let itcost = 6
let total = 7
let company = 8
let contact = 9
let contactmail = 10
let endusermail = 11
let address = 12
let country = 13
let status = 14
let suppliermail = 15
let currency = 16
let otherinfo = 17
let brand = 18
let comment = 19
let cc = 20
let emailTemp = HtmlService.createTemplateFromFile("MAIL")
let ws = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DATA")
let sd = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DATA2")
let data = ws.getRange("A2:V" + ws.getLastRow()).getValues()
let sData = sd.getRange("B2:J" + sd.getLastRow()).getValues()
let sInfo = sData.map(function (r) { return r[0] })
data = data.filter(function (r) { return r[14] == 'SENTNOW' })
if (data.length) {
let found = false
data.forEach(function (row) {
emailTemp.ts = row[timestamp].toLocaleString("da-DK")
emailTemp.po = row[poid]
emailTemp.co = row[contact]
emailTemp.cm = row[company]
emailTemp.ad = row[address]
emailTemp.cu = row[country]
emailTemp.cn = row[contactmail]
emailTemp.sk = row[sku]
emailTemp.de = row[description]
emailTemp.qt = row[qty]
emailTemp.it = (row[itcost]).toLocaleString("da-DK")
emailTemp.to = (row[total]).toLocaleString("da-DK")
emailTemp.ce = row[comment]
emailTemp.cy = row[currency]
emailTemp.eu = row[endusermail]
emailTemp.li = row[licenseid]
emailTemp.ot = row[otherinfo]
let indexSupp = sInfo.indexOf(row[15])
if (indexSupp > -1) {
//only change status if supplierdata email is found
found = true
emailTemp.spname = sData[indexSupp][1]
emailTemp.saddress1 = sData[indexSupp][2]
emailTemp.saddress2 = sData[indexSupp][3]
emailTemp.scountry = sData[indexSupp][4]
emailTemp.sterms = sData[indexSupp][5]
emailTemp.scurrency = sData[indexSupp][6]
emailTemp.sothers = sData[indexSupp][7]
emailTemp.vat = sData[indexSupp][8] * 100
emailTemp.totvat = (row[total] * sData[indexSupp][8]).toLocaleString("da-DK")
emailTemp.totandvat = (row[total] + (row[total] * sData[indexSupp][8])).toLocaleString("da-DK")
let subjectLine = "Subject line # " + row[poid]
let htmlMessage = emailTemp.evaluate().getContent()
//only send email if supplierdata email is found
try {
GmailApp.sendEmail(
row[suppliermail],
subjectLine,
"",
{ name: 'Name', htmlBody: htmlMessage, bcc: 'myemail#domain.com' })
}
catch (err) {
SpreadsheetApp.getUi().alert(err)
}
}
})
if (found) {
let sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DATA")
.getRange('O2:O')
.createTextFinder('SENTNOW')
.replaceAllWith('SENT')
}
}
}
Only problem is the date format emailTemp.ts = row[timestamp].toLocaleString("da-DK")
This give output date-format "11.2.2022 06.00.00" within the e-mail sent to the reciever.
What I wish is the date to be just "02/11/2022"
I tried emailTemp.ts = row[timestamp].toLocaleString("da-DK").getDisplayValue() but that was not working.
Any suggestions ?
You're going to have to figure out your time zone but try this.
emailTemp.ts = Utilities.formatDate(row[timestamp],"GMT","dd/MM/yyyy");
Reference
Utilities.formatDate()
I made a program in JavaFX with Kotlin I managed to make a CSV and TXT reading separated by ";" where I have efficiency problems and I don't know how I could improve the efficiency to make the SQL query construction.
fun generatedDelimited(filePath: String, table: String = "") {
val sourceFile = File(filePath)
var line: String?
var header: Array<String>? = null
val lines: MutableList<List<String>> = ArrayList()
try {
BufferedReader(FileReader(sourceFile)).use { br ->
header = br.readLine().split(";").toTypedArray();
while (br.readLine().also { line = it } != null) {
val values : Array<String> = line!!.split(";").toTypedArray();
lines.add(Arrays.asList(*values))
}
}
} catch (e: IOException) {
e.printStackTrace()
}
val joined = "INSERT INTO $table (${header!!.joinToString(separator = ",")})\n"
var textSelect = "${joined}SELECT * FROM ( \n"
var selectUnion = ""
var lineNo = 1
for (line in lines) {
var columnNo = 0
var comma = ", "
var select = "SELECT "
var union = "UNION ALL\n"
if (lines.size.equals(lineNo)) {
union = ""
}
for (value in line) {
if (columnNo == 1) {
select = ""
}
if (line.size.equals(columnNo+1)) {
comma = " FROM DUAL \n$union"
}
selectUnion += "$select'$value' as ${header!![columnNo]}$comma"
columnNo++
}
lineNo++
}
textSelect += "$selectUnion);"
querySQL.text = textSelect
}
Result:
INSERT INTO werwsf (DATA1,DATA2,DATA3,DATA4,DATA5)
SELECT * FROM (
SELECT 'HOLA1' as DATA1, 'HAKA2' as DATA2, 'HAD3' as DATA3, '' as DATA4, 'ASDAD5' as DATA5 FROM DUAL
UNION ALL
SELECT 'HOLA6' as DATA1, 'HAKA7' as DATA2, 'HAD8' as DATA3, 'FA9' as DATA4, 'ASDAD10' as DATA5 FROM DUAL
);
Is there a way to improve efficiency? With 1600 rows it takes 5 minutes
Thank you.
this should be an optimised version of your code:
I used kotlin standard joinToString functions, which uses StringBuilder under the hood like #0009laH advised. I also removed the redundant list <-> array conversions and replaced the splitting and then joining back the first line (header) by the replace function, because it has the same effect as in the original code and it is faster. All these changes should result in faster, more readable and more concise code
fun generatedDelimited(filePath: String, table: String = "") {
val sourceFile = File(filePath)
val fileLines: List<String> = sourceFile.readLines()
val header: String = fileLines.first().replace(';', ',')
val lines: List<List<String>> = fileLines.drop(1).map { line ->
line.split(";")
}
val selectUnion = lines.joinToString(separator = "UNION ALL\n") { line ->
line.withIndex().joinToString(separator = ", ", prefix = "SELECT", postfix = " FROM DUAL\n") { (columnNo, value) ->
"'$value' as ${header[columnNo]}"
}
}
querySQL.text = "INSERT INTO $table ($header)\nSELECT * FROM ( \n$selectUnion);"
}
I have a issue here for the connect mysql.
I have a vps that contain mysql server have a database name is 'tuyendungbg'. it's had table and data in there. But when i'm connect and query to select data, that have error for 'Table 'tuyendungbg.Careers' doesn't exist'.
here is my controller :
[HttpGet("/nganh-nghe/{slug?}")]
public IActionResult Index(string slug, [FromQuery(Name =
"p")] int currentPage, int
pageSize)
{
if (!string.IsNullOrEmpty(slug))
{
var career = _context.Careers.FirstOrDefault(x =>
x.Slug.Equals(slug));
if (career != null)
{
ViewBag.CareerName = career.CareerName;
//var qr = _context.Careers.ToList();
var qr = (from p in
_context.CompanyCareers.Where(x => x.CareerId ==
career.ID)
from b in _context.Companies.Where(x =>
x.Id == p.CompanyId)
from i in
_context.IndustrialAreas.Where(x => x.ID ==
b.IndustrialAreaId).DefaultIfEmpty()
select new CompanyModelView()
{
Id = b.Id,
CompanyName = b.CompanyName,
BasicSalary = b.BasicSalary,
Allowance = b.Allowance,
DateCreate = b.DateCreate,
JobTitle = b.JobTitle,
Src = b.Src,
_IndustrialArea = i,
Address = b.Address,
Slug = b.Slug,
WorkTypes = (from tc in
_context.CompanyWorkTypes.Where(x =>
x.CompanyId == b.Id)
from type in
_context.WorkTypes.Where(x => x.Id
==
tc.TypeId)
select type)
}
).OrderByDescending(x => x.DateCreate).ToList();
// var worktype = (from w in
_context.CompanyWorkTypes.Where(x =>
x.CompanyId
== qr.))
var totalCate = qr.Count();
if (pageSize <= 0) pageSize = 10;
int countPages =
(int)Math.Ceiling((double)totalCate / pageSize);
if (currentPage > countPages)
currentPage = countPages;
if (currentPage < 1)
currentPage = 1;
var pagingModel = new PagingModel()
{
countpages = countPages,
currentpage = currentPage,
generateUrl = (pageNumber) =>
Url.Action(nameof(Index), new
{
p = pageNumber,
pageSize = pageSize
})
};
ViewBag.pagingModel = pagingModel;
ViewBag.totalPost = totalCate;
ViewBag.cateIndex = (currentPage - 1) * pageSize;
var companies = qr.Skip((currentPage - 1) *
pageSize)
.Take(pageSize).ToList();
ViewBag.JobCount = companies.Count();
//Set slider menu
var leftSlider = new LeftSliderModel()
{
Areas = new SelectList(_context.Areas,
nameof(Area.ID),
nameof(Area.NameArea)),
Careers = new SelectList(_context.Careers,
nameof(Career.ID),
nameof(Career.CareerName)),
WorkTypes = _context.WorkTypes.ToList(),
Experiences = _context.Experiences.ToList()
};
ViewBag.LeftSlider = leftSlider;
return View(companies);
}
}
return NotFound();
}
I'm having a ton of trouble trying to access the nested json data (pasted at the bottom). I'm able write:
var dataResults = jsonResult["data"] as NSDictionary
In order to create a dictionary containing the data within "data", however, Xcode will not allow me to call on anything within "data" such as the information within "current_condition". I've tried to make current_condition it's own dictionary like so:
var results = dataResults["current_condition"] as NSDictionary
But it would seem that this is turning up as nil
I have also attempted accessing using the standard method for calling nested loops:
var dataResults = jsonResult["data"]["current_condition"] as NSDictionary
But this results in a compiler error.
Any help? Much appreciated!
Json data:
{
data = {
"current_condition" = (
{
cloudcover = 0;
humidity = 68;
"observation_time" = "01:39 AM";
precipMM = "0.0";
pressure = 1017;
"temp_C" = 20;
"temp_F" = 68;
visibility = 10;
weatherCode = 143;
weatherDesc = (
{
value = Mist;
}
);
weatherIconUrl = (
{
value = "http://cdn.worldweatheronline.net/images/wsymbols01_png_64/wsymbol_0006_mist.png";
}
);
winddir16Point = NE;
winddirDegree = 50;
windspeedKmph = 7;
windspeedMiles = 4;
}
);
request = (
{
query = "London, United Kingdom";
type = City;
}
);
weather = (
{
date = "2014-07-25";
precipMM = "1.5";
tempMaxC = 27;
tempMaxF = 81;
tempMinC = 14;
tempMinF = 57;
weatherCode = 353;
weatherDesc = (
{
value = "Light rain shower";
}
);
weatherIconUrl = (
{
value = "http://cdn.worldweatheronline.net/images/wsymbols01_png_64/wsymbol_0009_light_rain_showers.png";
}
);
winddir16Point = NE;
winddirDegree = 54;
winddirection = NE;
windspeedKmph = 15;
windspeedMiles = 10;
},
{
date = "2014-07-26";
precipMM = "5.8";
tempMaxC = 28;
tempMaxF = 83;
tempMinC = 16;
tempMinF = 61;
weatherCode = 176;
weatherDesc = (
{
value = "Patchy rain nearby";
}
);
weatherIconUrl = (
{
value = "http://cdn.worldweatheronline.net/images/wsymbols01_png_64/wsymbol_0009_light_rain_showers.png";
}
);
winddir16Point = NNE;
winddirDegree = 12;
winddirection = NNE;
windspeedKmph = 11;
windspeedMiles = 7;
},
{
date = "2014-07-27";
precipMM = "0.2";
tempMaxC = 26;
tempMaxF = 80;
tempMinC = 13;
tempMinF = 55;
weatherCode = 116;
weatherDesc = (
{
value = "Partly Cloudy";
}
);
weatherIconUrl = (
{
value = "http://cdn.worldweatheronline.net/images/wsymbols01_png_64/wsymbol_0002_sunny_intervals.png";
}
);
winddir16Point = NW;
winddirDegree = 321;
winddirection = NW;
windspeedKmph = 14;
windspeedMiles = 9;
},
{
date = "2014-07-28";
precipMM = "1.9";
tempMaxC = 26;
tempMaxF = 78;
tempMinC = 12;
tempMinF = 54;
weatherCode = 116;
weatherDesc = (
{
value = "Partly Cloudy";
}
);
weatherIconUrl = (
{
value = "http://cdn.worldweatheronline.net/images/wsymbols01_png_64/wsymbol_0002_sunny_intervals.png";
}
);
winddir16Point = N;
winddirDegree = 351;
winddirection = N;
windspeedKmph = 13;
windspeedMiles = 8;
},
{
date = "2014-07-29";
precipMM = "0.0";
tempMaxC = 28;
tempMaxF = 82;
tempMinC = 16;
tempMinF = 60;
weatherCode = 113;
weatherDesc = (
{
value = Sunny;
}
);
weatherIconUrl = (
{
value = "http://cdn.worldweatheronline.net/images/wsymbols01_png_64/wsymbol_0001_sunny.png";
}
);
winddir16Point = NNW;
winddirDegree = 329;
winddirection = NNW;
windspeedKmph = 13;
windspeedMiles = 8;
}
);
};
}
Oddly enough, I have a sample weather app that I converted to Swift. I get my data elsewhere, but I found this library to be a great way to deal with JSON in Swift: https://github.com/dankogai/swift-json/. Much cleaner and easier.
It's because the subscript in Dictionary returns an optional:
subscript (key: KeyType) -> ValueType?
Meaning you have to unwrap the optional before you can downcast:
let dataResults = jsonResult["data"]! as NSDictionary
let results = dataResults["current_condition"]! as NSDictionary
As of Beta 3 you can access the value directly without downcasting, like this:
let dataResults = jsonResult["data"]!
let results = dataResults["current_condition"]
However I would suggest you wrap it around an if-let to make sure you don't unwrap nil values.
I am able to do this query just fine with the test repository which is In Memory
when I move to the sqlRepository I get this error
Unsupported overload used for query operator 'Intersect'.
I assume it is because sending the query to sql is too complicated for Linq to Sql to do when it is not dealing with the Model.Model.Talent Type. Is there some way around doing a search like this with Intersect?
thanks
public class TalentService : ITalentService
{
ITalentRepository _repository = null;
private IQueryable<Talent> BasicSearch(string searchExpression)
{
IQueryable<Talent> t;
string[] sa = searchExpression.Trim().ToLower().Replace(" ", " ").Split(' ');
t = _repository.GetTalents();
foreach (string s in sa)
{
t = t.Intersect(AddBasicSearch(s), new TalentComparer());
}
return t;
}
private IQueryable<Talent> AddBasicSearch(string s)
{
IQueryable<Talent> t2 = _repository.GetTalents()
.Where(tal => tal.EyeColor.ToString().ToLower().Contains(s)
|| tal.FirstName.ToLower().Contains(s)
|| tal.LastName.ToLower().Contains(s)
|| tal.LanguagesString.ToLower().Contains(s)
);
return t2;
}
}
public class SqlTalentRepository:ITalentRepository
{
public IQueryable<Model.Model.Talent> GetTalents()
{
var tal = from t in _db.Talents
let tLanguage = GetTalentLanguages(t.TalentID)
where t.Active == true
select new Model.Model.Talent
{
Id = t.TalentID,
FirstName = t.FirstName,
LastName = t.LastName,
TalentLanguages = new LazyList<Model.Model.TalentLanguage>(tLanguage),
LanguagesString = t.TalentLanguages.ToLanguageNameString(_LanguageRepository.GetLanguages())
};
return tal ;
}
public IQueryable<Model.Model.TalentLanguage> GetTalentLanguages(int iTalentId)
{
var q = from y in this.talentLanguageList
let Languages = _LanguageRepository.GetLanguages()
where y.TalentId == iTalentId
select new Model.Model.TalentLanguage
{
TalentLanguageId = y.TalentLanguageId,
TalentId = y.TalentId,
LanguageId = y.LanguageId,
Language = Languages.Where(x => x.LanguageId == y.LanguageId).SingleOrDefault()
};
return q.AsQueryable<Model.Model.TalentLanguage>();
}
}
public static class TalentExtensions
{
public static string ToLanguageNameString(this IEnumerable<TalentLanguage> source
, IEnumerable<Model.Model.Language> allLanguages)
{
StringBuilder sb = new StringBuilder();
const string del = ", ";
foreach (TalentLanguage te in source)
{
sb.AppendFormat("{0}{1}", allLanguages
.Where(x => x.LanguageId == te.LanguageID).SingleOrDefault().LanguageName, del);
}
string sReturn = sb.ToString();
if (sReturn.EndsWith(del))
sReturn = sReturn.Substring(0, sReturn.Length - del.Length);
return sReturn;
}
}
public class TestTalentRepository : ITalentRepository
{
IList<Talent> talentList;
public TestTalentRepository(ILanguageRepository _LanguageRepo )
{
this._LanguageRepository = _LanguageRepo;
talentList = new List<Talent>();
talentLanguageList = new List<TalentLanguage>();
for (int i = 0; i < 55; i++)
{
var t = new Talent();
t.Id = i;
t.FirstName = (i % 3 == 0) ? "Ryan" : "Joe";
t.LastName = (i % 2 == 0) ? "Simpson" : "Zimmerman";
AddLanguagesToTestTalent(i, t);
talentList.Add(t);
}
}
private void AddLanguagesToTestTalent(int i, Talent t)
{
IList<Language> Languages = _LanguageRepository.GetLanguages().ToList<Language>();
Random rLanguages = new Random();
int numLanguages = rLanguages.Next(Languages.Count - 1) + 1;
t.TalentLanguages = new LazyList<TalentLanguage>();
for (int j = 0; j < numLanguages; j++)
{
var x = new TalentLanguage();
x.TalentLanguageId = j;
x.TalentId = i;
Random random2 = new Random();
int rand = random2.Next(Languages.Count);
var y = Languages.ElementAtOrDefault(rand);
Languages.RemoveAt(rand);
x.Language = y;
x.LanguageId = y.LanguageId;
t.TalentLanguages.Add(x);
}
}
public IQueryable<Talent> GetTalents()
{
var ts = from t in this.talentList
let tLanguage = GetTalentLanguages(t.Id)
where t.Active == true
select new Model.Model.Talent
{
Id = t.Id,
FirstName = t.FirstName,
LastName = t.LastName,
TalentLanguages = new LazyList<Model.Model.TalentLanguage>(tLanguage),
LanguagesString = t.TalentLanguages.ToLanguageNameString(_LanguageRepository.GetLanguages()),
City = t.City,
};
return ts.AsQueryable<Model.Model.Talent>();
}
public IQueryable<Model.Model.TalentLanguage> GetTalentLanguages(int iTalentId)
{
var q = from y in this.talentLanguageList
let Languages = _LanguageRepository.GetLanguages()
where y.TalentId == iTalentId
select new Model.Model.TalentLanguage
{
TalentLanguageId = y.TalentLanguageId,
TalentId = y.TalentId,
LanguageId = y.LanguageId,
Language = Languages.Where(x => x.LanguageId == y.LanguageId).SingleOrDefault()
};
return q.AsQueryable<Model.Model.TalentLanguage>();
}
}
If you're trying to find entries which match all of those criteria, you just need multiple where clauses:
private static readonly char[] SplitDelimiters = " ".ToCharArray();
private IQueryable<Talent> BasicSearch(string search)
{
// Just replacing " " with " " wouldn't help with "a b"
string[] terms = search.Trim()
.ToLower()
.Split(SplitDelimiters,
StringSplitOptions.RemoveEmptyEntries);
IQueryable<Talent> query = _repository.GetTalents();
foreach (string searchTerm in terms)
{
query = AddBasicSearch(query, searchTerm);
}
return query;
}
private IQueryable<Talent> AddBasicSearch(IQueryable<Talent> query, string s)
{
return query.Where(tal =>
tal.EyeColor.ToString().ToLower().Contains(s)
|| tal.FirstName.ToLower().Contains(s)
|| tal.LastName.ToLower().Contains(s)
|| tal.LanguagesString.ToLower().Contains(s)
);
}