Nested IEnumerable collections within Class filtering on multiple conditions - c#

I may not being using the correct term "nested", but you can see the 2 classes I have below. IEnumerable<OperationTask> is in the IEnumerable<AxApp>.
I hope I can explain this correctly:
I have a method that is reading values from a txt file into a string[]
string[] appNames = _appNamesRepository.GetAppNameListFromInputFile(fileName);
Then I create an IEnumerable<AxApp> collection with a method that reads a SQL table and returns the AxApp properties for each app value in the txt file.
IEnumerable<AxApp> allAxApps = _axAppRepository.GetAllAxAppsInList(appNames);
I need to filter the IEnumerable<AxApp> collection based on specific criteria from values in the IEnumerable<OperationTask>. I can get a basic lambda search to work, but I can't return the correct result if I have more than a couple values I'm basing this on.
For example the below will only return an IEnumerable<AxApp> if the appid, operationType, and operationStatus.Incomplete are NOT in IEnumerable<OperationTasks>.
var test = allAxApps.Where(app =>
!app.operationTasks
.Any(task => task.appId == app.appid &&
task.operationType == operationType &&
task.operationStatus != Status.Incomplete));
HOWEVER, I need to go a step further, if the operationType == "Differential", I can only return the AxApp IF IN IEnmerable<OperationTask> there is a collection where type = "NewConversion", status = "Complete", but NO type = "Finish", but can include types = "Differential"
public class AxApp
{
public AxApp()
{
}
public AxApp(int id, string appname, string dlname)
{
this.appname = appname;
appid = id;
this.dlname = dlname;
}
public string appname { get; set; }
public int appid { get; set; }
public string dlname { get; set; }
public string dtname { get; set; }
public int flags { get; set; }
public IEnumerable<AxDlsd> dlsdRecords { get; set; }
public IEnumerable<AxDl> dlRecords { get; set; }
public IEnumerable<OperationTask> operationTasks { get; set; }
public DateTime startMerge { get; set; }
public DateTime endMerge { get; set; }
}
public class OperationTask
{
public int operationId { get; set; }
public int appId { get; set; }
public OperationType operationType { get; set; }
public Status operationStatus { get; set; }
public DateTime startTime { get; set; }
public DateTime endTime { get; set; }
}
Method that returns the AppData from any value in the string[]
public IEnumerable<AxApp> GetAllAxAppsInList(string[] appNamesInput)
{
string query = #"SELECT appid, appname, dlname, dtname, flags FROM dbo.ae_apps WHERE appname = #_appname";
string opQuery = #"SELECT operationId, appId, operationType, operationStatus, startTime, endTime FROM dbo.RDS_ConversionOperationsHistory WHERE appid = #_appId";
using (var connection = _dbConnectionFactory.GetAxDbConnection())
{
foreach (string appname in appNamesInput)
{
AxApp result = connection.QuerySingle<AxApp>(query, new { _appname = appname });
result.operationTasks = connection.Query<OperationTask>(opQuery, new { _appId = result.appid });
yield return result;
}
}
}
IEnumerable for AxApp/OperationTask
[0] = {RDS.Conversion.UtilityLibrary.Models.AxApp}
[0] {RDS.Conversion.UtilityLibrary.Models.AxApp} RDS.Conversion.UtilityLibrary.Models.AxApp
appid 1 int
appname "PLIC_CENT_1" string
dlRecords null System.Collections.Generic.IEnumerable<RDS.Conversion.UtilityLibrary.Models.AxDl
dlname "ae_dlsd1_SIM" string
dlsdRecords null System.Collections.Generic.IEnumerable<RDS.Conversion.UtilityLibrary.Models.AxDlsd>
dtname "ae_dt1" string
endMerge {1/1/0001 12:00:00 AM} System.DateTime
flags 16384 int
operationTasks Count = 3 System.Collections.Generic.IEnumerable<RDS.Conversion.UtilityLibrary.Models.OperationTask> {System.Collections.Generic.List<RDS.Conversion.UtilityLibrary.Models.OperationTask>}
startMerge {1/1/0001 12:00:00 AM} System.DateTime
operationTasks Count = 3 System.Collections.Generic.IEnumerable<RDS.Conversion.UtilityLibrary.Models.OperationTask> {System.Collections.Generic.List<RDS.Conversion.UtilityLibrary.Models.OperationTask>}
[0] {RDS.Conversion.UtilityLibrary.Models.OperationTask} RDS.Conversion.UtilityLibrary.Models.OperationTask
appId 1 int
endTime {1/1/0001 12:00:00 AM} System.DateTime
operationId 18 int
operationStatus Complete RDS.Conversion.UtilityLibrary.Models.Status
operationType NewConversion RDS.Conversion.UtilityLibrary.Models.OperationType
startTime {9/28/2018 12:53:51 PM} System.DateTime

I'm not sure if this is what you're looking for but, it may get you in the right direction.
test = allAxApps.Where(app =>
{
var tasks = app.operationTasks.ToList();
var differentialCondition = false;
if (operationType == OperationType.Differential)
{
var hasCompletedNewConversion = tasks.Any(task =>
task.operationType == OperationType.NewConversion &&
task.operationStatus == Status.Complete);
var hasFinish = tasks.Any(task => task.operationType == OperationType.Finish);
differentialCondition = hasCompletedNewConversion && !hasFinish;
}
var hasIncomplete = tasks.Any(task =>
task.appId == app.appid &&
task.operationType == operationType &&
task.operationStatus == Status.Incomplete);
return differentialCondition && !hasIncomplete;
});

Related

Entity Framework Core: FromSqlInterpolated(). An item with the same key has already been added. Key: Id

I want to get a list of my friends' stories. It didn't work through LINQ, but I was able to write a good SQL query that really works and returns what I need. I use .NET 7 & EF Core 7.
int userId = 1;
StoryContainerRto test = await _context.StoryContainer
.FromSqlInterpolated($#"SELECT s."Id", s."AuthorId", u."Id", u."AccountHeaderUrl", u."AvatarUrl", u."Description", u."Email", u."IsAuthorOfQualityContent", u."IsDeleted", u."IsInShadowBan", u."IsVerifiedProfile", u."LinkInBio", u."MedalsAmount", u."Name", u."Nickname", u."PasswordHash", u."PasswordSalt", u."PhoneNumber", u."PhoneNumberPrefix", u."PhoneNumberVerefied", u."RegistrationDateTime", u."TelegramId", u."TelegramVerifyingChatId"
FROM ""StoryContainer"" as s
INNER JOIN ""StoryContentRefs"" as scr ON scr.""StoryId"" = s.""Id""
LEFT JOIN ""User"" as u ON u.""Id"" = s.""AuthorId""
LEFT JOIN ""StoryContentRefRtoUserRto"" as whoView ON whoView.""ViewedId"" = {userId} AND whoView.""ViewedStoriesId"" = scr.""Id""
WHERE s.""AuthorId"" IN (
SELECT u.""Id""
FROM ""UserFriend"" as f, ""User"" as u
WHERE
CASE
WHEN f.""FirstUserFriendId"" = {userId}
THEN f.""SecondUserFriendId"" = u.""Id""
WHEN f.""SecondUserFriendId"" = {userId}
THEN f.""FirstUserFriendId"" = u.""Id""
END
)
AND scr.""CreateTimestamp"" >= NOW() - '1 day'::INTERVAL
AND scr.""IsDelete"" = false").ToListAsync();
Output:
System.ArgumentException: An item with the same key has already been added. Key: Id
If you execute this code, the SQL query will be identical (given that the SQL query is lightweight. It just gets the story and the author, but does not get the rest of the information, because it is needed only for clarity)
StoryContainerRto entity = await _context.StoryContainer
.AsNoTracking()
.Include(e => e.Author)
.Where(e => e.AuthorId == 1)
.ToListAsync();
Generated SQL (note the duplication of the "Id" column):
SELECT s."Id", s."AuthorId", u."Id", u."AccountHeaderUrl", u."AvatarUrl", u."Description", u."Email", u."IsAuthorOfQualityContent", u."IsDeleted", u."IsInShadowBan", u."IsVerifiedProfile", u."LinkInBio", u."MedalsAmount", u."Name", u."Nickname", u."PasswordHash", u."PasswordSalt", u."PhoneNumber", u."PhoneNumberPrefix", u."PhoneNumberVerefied", u."RegistrationDateTime", u."TelegramId", u."TelegramVerifyingChatId"
FROM "StoryContainer" AS s
INNER JOIN "User" AS u ON s."AuthorId" = u."Id"
WHERE s."AuthorId" = 1
User table:
[Table("User")]
public class UserRto
{
[Key] public int Id { get; set; }
[Required] public string Nickname { get; set; }
public string? Email { get; set; }
[Required] public byte[] PasswordHash { get; set; }
[Required] public byte[] PasswordSalt { get; set; }
public string? Name { get; set; }
public string? Description { get; set; }
public string? LinkInBio { get; set; }
public int MedalsAmount { get; set; }
public string? AvatarUrl { get; set; }
public bool IsDeleted { get; set; }
public bool? IsVerifiedProfile { get; set; }
public bool? IsAuthorOfQualityContent { get; set; }
public bool IsInShadowBan { get; set; }
public DateTime RegistrationDateTime { get; set; }
public string? PhoneNumberPrefix { get; set; }
public string? PhoneNumber { get; set; }
public bool PhoneNumberVerefied { get; set; }
public string? TelegramId { get; set; }
public string? TelegramVerifyingChatId { get; set; }
public string? AccountHeaderUrl { get; set; }
public List<FriendInvitationRto> FriendInvitationsSent { get; set; }
public List<FriendInvitationRto> FriendInvitationsReceived { get; set; }
public List<UserFriendRto> FirstFriends { get; set; }
public List<UserFriendRto> SecondFriends { get; set; }
public List<StoryContentRefRto> ViewedStories { get; set; }
public StoryContainerRto StoryContainer { get; set; }
}
Story table:
[Table("StoryContainer")]
public class StoryContainerRto
{
public int Id { get; set; }
public int AuthorId { get; set; }
public UserRto Author { get; set; }
public List<StoryContentRefRto> Items { get; set; }
}
How do I complete the request? I understand that the fact is that 3 columns of "Id" come from three tables. But at the same time, if you look at the request generated by EF itself, then there are also 2 "Ids". How do I execute such a request correctly?
https://makolyte.com/ef-core-select-queries-involving-multiple-table/
There is an example of code using INNER JOIN like mine. I do not know why the same approach does not work for me
I also applied the AS operator to all the "Id" columns, but in that case I get this error:
The required column 'Id' was not present in the results of a 'FromSql' operation
I was able to solve this problem using a direct SQL query to the database, and then analyzed the information myself
List<StoryRto> friendsStories = new();
using (NpgsqlCommand command = (NpgsqlCommand)(_context as PotokContext)!.Database.GetDbConnection().CreateCommand())
{
command.CommandText = $#"SELECT s.*, scr.*, u.*, whoView.""ViewedId"" as ""IViewThis""
FROM ""Stories"" as s
INNER JOIN ""StoryContentRefs"" as scr ON scr.""StoryId"" = s.""Id""
INNER JOIN ""User"" as u ON u.""Id"" = s.""AuthorId""
LEFT JOIN ""StoryContentRefRtoUserRto"" as whoView ON whoView.""ViewedId"" = 1 AND whoView.""ViewedStoriesId"" = scr.""Id""
WHERE s.""AuthorId"" IN (
SELECT u.""Id""
FROM ""UserFriend"" as f, ""User"" as u
WHERE
CASE
WHEN f.""FirstUserFriendId"" = 1
THEN f.""SecondUserFriendId"" = u.""Id""
WHEN f.""SecondUserFriendId"" = 1
THEN f.""FirstUserFriendId"" = u.""Id""
END
)
AND scr.""CreateTimestamp"" >= NOW() - '1 day'::INTERVAL
AND scr.""IsDelete"" = false
LIMIT {count}
OFFSET {skipCount}";
(_context as PotokContext)!.Database.OpenConnection();
using (var reader = command.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
// Stories table
int storyId = reader.GetInt32(0);
int authorId = reader.GetInt32(1);
// StoryContentRefs table
int scrId = reader.GetInt32(2);
int scrStoryId = reader.GetInt32(3);
string scrStoryContentRef = reader.GetString(4);
bool scrIsDelete = reader.GetBoolean(5);
DateTime scrCreateTimestamp = reader.GetDateTime(6);
// UserTable
int userId = reader.GetInt32(7);
string userNickname = reader.GetString(8);
string? userEmail = reader.IsDBNull(9) ? null : reader.GetString(9);
// password hash and salt will not be included
string? userName = reader.IsDBNull(12) ? null : reader.GetString(12);
string? userDescription = reader.IsDBNull(13) ? null : reader.GetString(13);
string? userLinkInBio = reader.IsDBNull(14) ? null : reader.GetString(14);
int userMedalsAmount = reader.GetInt32(15);
string? userAvatarUrl = reader.IsDBNull(16) ? null : reader.GetString(16);
bool userIsDeleted = reader.GetBoolean(17);
bool? userIsVerifiedProfile = reader.IsDBNull(18) ? null : reader.GetBoolean(18);
DateTime userRegistrationDateTime = reader.GetDateTime(19);
bool? userIsAuthorOfQualityContent = reader.IsDBNull(20) ? null : reader.GetBoolean(20);
string? userPhoneNumber = reader.IsDBNull(21) ? null : reader.GetString(21);
string? userPhoneNumberPrefix = reader.IsDBNull(22) ? null : reader.GetString(22);
bool userPhoneNumberVerified = reader.GetBoolean(23);
string? userTelegramId = reader.IsDBNull(24) ? null : reader.GetString(24);
string? userTelegramVerifyingChatId = reader.IsDBNull(25) ? null : reader.GetString(25);
bool userIsInShadowBan = reader.GetBoolean(26);
string? userAccountHeaderUrl = reader.IsDBNull(27) ? null : reader.GetString(27);
// WhoViewStory relation
int? iViewThis = reader.IsDBNull(28) ? null : reader.GetInt32(28);
UserRto user = new()
{
Id = userId,
Nickname = userNickname,
Email = userEmail,
Name = userName,
Description = userDescription,
LinkInBio = userLinkInBio,
MedalsAmount = userMedalsAmount,
AvatarUrl = userAvatarUrl,
IsDeleted = userIsDeleted,
IsVerifiedProfile = userIsVerifiedProfile,
RegistrationDateTime = userRegistrationDateTime,
IsAuthorOfQualityContent = userIsAuthorOfQualityContent,
PhoneNumber = userPhoneNumber,
PhoneNumberPrefix = userPhoneNumberPrefix,
PhoneNumberVerefied = userPhoneNumberVerified,
TelegramId = userTelegramId,
TelegramVerifyingChatId = userTelegramVerifyingChatId,
IsInShadowBan = userIsInShadowBan,
AccountHeaderUrl = userAccountHeaderUrl
};
List<UserRto> viewed = new();
if (iViewThis != null) viewed.Add(user);
StoryContentRefRto storyContentRef = new()
{
Id = scrId,
StoryId = scrStoryId,
ContentRefs = scrStoryContentRef,
IsDelete = scrIsDelete,
CreateTimestamp = scrCreateTimestamp,
Viewed = viewed
};
if (friendsStories.FirstOrDefault(e => e.Id == scrStoryId) == null)
{
// Create new
StoryRto story = new()
{
Id = storyId,
AuthorId = authorId,
Author = user,
Items = new() { storyContentRef }
};
friendsStories.Add(story);
}
else
{
// Add to existing
StoryRto story = friendsStories.First(e => e.Id == scrStoryId);
story.Items.Add(storyContentRef);
}
}
}
else
{
Console.WriteLine("No rows found.");
}
}
}

Assign 0 to Id to Null value

Can someone help me to assign the value of 0 if no records found for this Linq query. Currently I am returning null, But i need to assign 0 if it is null.
//Linq Query
var ideasQuery = from b in db.StarLive_StarIBox_Ideas.Where(b => b.UserId == userid)
select new IdeasDTO()
{
IdeaId = b.IdeaId,
Idea = b.Idea,
UserName = b.StarLive_Sys_Users.cLogName,
DatePosted = b.DatePosted.ToString(),
Problem = b.StarLive_StarIBox_Problems.Problems,
Department = b.StarLive_Sys_Users.nDeptID.ToString(),
LikeId=b.StarLive_StarIBox_Likes.Where
(l=>l.IdeaId==b.IdeaId && l.LikedBy==b.UserId).FirstOrDefault().LikeID
};
//DTO Class
public class IdeasDTO
{
[DataMember]
public int IdeaId { get; set; }
[DataMember]
public string UserName { get; set; }
[DataMember]
public string Idea { get; set; }
[DataMember]
public string DatePosted { get; set; }
[DataMember]
public string Problem { get; set; }
[DataMember]
public int Likes { get; set; }
[DataMember]
public bool Liked { get; set; }
[DataMember]
public string Department { get; set; }
[DataMember]
public int? LikeId { get; set; }
}
//Postman Response
{
"IdeaId": 21,
"UserName": "Gowthamb",
"Idea": "This is an Idea",
"DatePosted": "Feb 14 2019 3:19PM",
"Problem": "Problem 1",
"Likes": 0,
"Liked": false,
"Department": "1",
"LikeId": null
}
Please help
Change this:
//Linq Query
var ideasQuery = from b in db.StarLive_StarIBox_Ideas.Where(b => b.UserId == userid)
select new IdeasDTO()
{
IdeaId = b.IdeaId,
Idea = b.Idea,
UserName = b.StarLive_Sys_Users.cLogName,
DatePosted = b.DatePosted.ToString(),
Problem = b.StarLive_StarIBox_Problems.Problems,
Department = b.StarLive_Sys_Users.nDeptID.ToString(),
LikeId=b.StarLive_StarIBox_Likes.Where
(l=>l.IdeaId==b.IdeaId && l.LikedBy==b.UserId).FirstOrDefault().LikeID
};
To this:
//Linq Query
var ideasQuery = from b in db.StarLive_StarIBox_Ideas.Where(b => b.UserId == userid)
select new IdeasDTO()
{
IdeaId = b.IdeaId,
Idea = b.Idea,
UserName = b.StarLive_Sys_Users.cLogName,
DatePosted = b.DatePosted.ToString(),
Problem = b.StarLive_StarIBox_Problems.Problems,
Department = b.StarLive_Sys_Users.nDeptID.ToString(),
LikeId=b.StarLive_StarIBox_Likes.Where
(l=>l.IdeaId==b.IdeaId && l.LikedBy==b.UserId).FirstOrDefault().LikeID ?? 0
};
Explanation:
LikeID is a int? it means that it is nullable.
the ?? operator, means that if the result is null it must assign the value on the right, which will be 0 in this case:
LikeId=b.StarLive_StarIBox_Likes.Where(l=>l.IdeaId==b.IdeaId && l.LikedBy==b.UserId).FirstOrDefault().LikeID ?? 0
You can write something like this
change LikeId=b.StarLive_StarIBox_Likes to LikeId=b.StarLive_StarIBox_Likes == null ? 0 : b.StarLive_StarIBox_Likes

Elastic search nest dynamic query with object initializer NEST 5.x

Hi I'm a new to elastic nest API and I'm using nest 5.x. I'm currently developing some kind of advanced search page so when user doesn't check a criteria i don't have to include that filter on my query. I'm trying to combine 2 queries under must operator with object initializer approach using nest. How to achieve it? I'm following the example on [https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/bool-queries.html]
var secondSearchResponse = client.Search(new
SearchRequest {
Query = new TermQuery { Field = Field(p => p.Name), Value = "x" } &&
new TermQuery { Field = Field(p => p.Name), Value = "y" } });
But it doesnt work cause Field class doesnt accept type arguments.
I also tried to followed this approach from this topic
[Nest Elastic - Building Dynamic Nested Query
here is my code
public HttpResponseMessage GetSearchResult([FromUri] SearchModels queries)
{
try
{
///
string result = string.Empty;
result += "queryfields + " + queries.queryfields == null ? string.Empty : queries.queryfields;
result += "datefrom + " + queries.datefrom == null ? string.Empty : queries.datefrom;
result += "dateto + " + queries.dateto == null ? string.Empty : queries.dateto;
result += "emitentype + " + queries.emitentype == null ? string.Empty : queries.emitentype;
QueryContainer andQuery = null;
//List<QueryContainer> QueryContainers = new List<QueryContainer>();
IDXNetAnnouncement record = new IDXNetAnnouncement
{
kode_emiten = queries.kodeemiten
};
#region keyword
if (!string.IsNullOrEmpty(queries.queryfields))
{
var val = queries.queryfields;
TermQuery tq = new TermQuery
{
Field = queries.queryfields,
Value = val
};
if (andQuery == null)
andQuery = tq;
else
andQuery &= tq;
//QueryContainers.Add(tq);
}
#endregion keyword
#region kodeemiten
if (!string.IsNullOrEmpty(queries.kodeemiten))
{
var val = queries.kodeemiten;
TermQuery tq = new TermQuery
{
Name = "kode_emiten",
Field = record.kode_emiten,
Value = val
};
if (andQuery == null)
andQuery = tq;
else
andQuery &= tq;
//QueryContainers.Add(tq);
}
#endregion
#region date
if (!string.IsNullOrEmpty(queries.datefrom) && !string.IsNullOrEmpty(queries.dateto))
{
DateRangeQuery dq = new DateRangeQuery();
dq.Name = "tglpengumuman";
dq.LessThanOrEqualTo = DateMath.Anchored(queries.dateto);
dq.GreaterThanOrEqualTo = DateMath.Anchored(queries.datefrom);
dq.Format = "dd/mm/yyyy";
if (andQuery == null)
andQuery = dq;
else
andQuery &= dq;
//QueryContainers.Add(dq);
}
#endregion keyword
var reqs = (ISearchResponse<IDXNetAnnouncement>)null;
if (andQuery != null)
{
reqs = conn.client.Search<IDXNetAnnouncement>(s => s
.AllIndices()
.AllTypes()
.From(queries.indexfrom)
.Size(queries.pagesize)
.Query(q => q.Bool(qb => qb.Must(m => m.MatchAll() && andQuery))));
//var json = conn.client.Serializer.SerializeToString(reqs.ApiCall.ResponseBodyInBytes);
}
else
{
reqs = conn.client.Search<IDXNetAnnouncement>(s => s
.AllIndices()
.AllTypes()
.From(queries.indexfrom)
.Size(queries.pagesize)
.Query(m => m.MatchAll()));
}
//var reqstring = Encoding.UTF8.GetString(conn.client.);
var reslts = this.conn.client.Serializer.SerializeToString(reqs,SerializationFormatting.Indented);
var resp = new HttpResponseMessage()
{
Content = new StringContent(reslts)
};
resp.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
return resp;
}
catch (Exception e)
{
var resp = new HttpResponseMessage()
{
Content = new StringContent(e.ToString())
};
resp.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
return resp;
}
}
But that returns zero result. How to achieve this? Thx anyway.
EDIT :
This is the params variabel definition. Its apoco model of search keywords
public class SearchModels
{
public string queryfields { get; set; }
public string datefrom { get; set; }
public string dateto { get; set; }
public string emitentype { get; set; }
public string kodeemiten { get; set; }
public string issuercode { get; set; }
public int indexfrom { get; set; }
public int pagesize { get; set; }
}
IDXNetAnnouncement is a poco model of search result. Its actualy a document type which is stored on the elastic server
public class IDXNetAnnouncement
{
public string perihalpengumuman { get; set; }
public string attachments { get; set; }
public string createddate { get; set; }
public bool efekemiten_spei { get; set; }
public string jmsxgroupid { get; set; }
public string tglpengumuman { get; set; }
public object errordescription { get; set; }
public string ESversion { get; set; }
public int oldfinalid { get; set; }
public bool efekemiten_etf { get; set; }
public object errorcode { get; set; }
public string jenisemiten { get; set; }
public int pkid { get; set; }
public string judulpengumuman { get; set; }
public string form_id { get; set; }
public bool efekemiten_eba { get; set; }
public string jenispengumuman { get; set; }
public string nopengumuman { get; set; }
public string kode_emiten { get; set; }
public string divisi { get; set; }
public string EStimestamp { get; set; }
public bool efekemiten_obligasi { get; set; }
public long finalid { get; set; }
public bool efekemiten_saham { get; set; }
public string kodedivisi { get; set; }
public string SearchTerms
{
get
{
return string.Format("{0} {1} {2}", judulpengumuman, kode_emiten, nopengumuman);
}
}
}
But it doesnt work cause Field class doesnt accept type arguments.
You need to ensure that you include a using static directive for Nest.Infer i.e.
using static Nest.Infer;
with the rest of the using directives.
.Query(q => q.Bool(qb => qb.Must(m => m.MatchAll() && andQuery))));
No need to wrap in a Must(), just do
.Query(q => q.MatchAll() && andQuery)
which will wrap both queries in a bool query must clause. You also don't need to null check andQuery because NEST is smart enough to not combine the two queries if either or both are null.
if (!string.IsNullOrEmpty(queries.queryfields))
{
var val = queries.queryfields;
TermQuery tq = new TermQuery
{
Field = queries.queryfields,
Value = val
};
if (andQuery == null)
andQuery = tq;
else
andQuery &= tq;
//QueryContainers.Add(tq);
}
NEST has the concept of conditionless queries so you don't need to check it queries.queryfields is null or empty, simply build the query and add it to andQuery. So it would become
var val = queries.queryfields;
andQuery &= new TermQuery
{
Field = queries.queryfields,
Value = val
};
Aside
All of the NEST documentation is generated from source code; you can trace back to the original source file by clicking on any edit link within the documentation. This will take you to a github page, such as this one for bool queries. From here, the document contains an important note that links back to the original source.

Find Unique count on field using LINQ

I am trying to determine the Distinct count for a particular field in a collection of objects.
private static RemittanceCenterBatchSummaryListModel SummarizeFields(RemittanceCenterSummaryListModel remittanceCenterSummaryListModel)
{
var result = remittanceCenterSummaryListModel.RemittanceBatchSummaryRecord.GroupBy(x => new{x.FileId, x.SourceFileName, x.BatchCode, x.BatchType})
.Select(x => new RemittanceCenterBatchSummarizedModel()
{
FileId = x.Key.FileId,
SourceFileName = x.Key.SourceFileName,
BatchCode = x.Key.BatchCode,
BatchType = x.Key.BatchType,
DetailRecordCountAdc = x.Count(y => y.BillingSystemCode == BillingSystemCode.Adc),
DetailRecordCountNotAdc = x.Count(y => y.BillingSystemCode == BillingSystemCode.Exd),
AmountAdc = x.Where(y => y.BillingSystemCode == BillingSystemCode.Adc).Sum(y => y.PaymentAmount),
AmountNotAdc = x.Where(y => y.BillingSystemCode == BillingSystemCode.Exd).Sum(y => y.PaymentAmount),
UniqueFileCount = x.Select(y => x.Key.FileId).Distinct().Count()
});
return CreateSummaryListModel(result);
}
Input entities:
public class RemittanceCenterSummaryListModel
{
public RemittanceCenterSummaryListModel()
{
this.RemittanceBatchSummaryRecord = new List<RemittanceBatchProcessingModel>();
}
public List<RemittanceBatchProcessingModel> RemittanceBatchSummaryRecord { get; private set; }
}
public class RemittanceCenterBatchSummarizedModel
{
public string FileId { get; set; }
public string SourceFileName { get; set; }
public string BatchCode { get; set; }
public string BatchType { get; set; }
public int DetailRecordCountAdc { get; set; }
public int DetailRecordCountNotAdc { get; set; }
public int DetailRecordCountTotal { get; set; }
public decimal AmountAdc { get; set; }
public decimal AmountNotAdc { get; set; }
public decimal AmountTotal { get; set; }
public BillingSystemCode BillingSystemCode { get; set; }
public int UniqueFileCount { get; set; }
}
private static RemittanceCenterBatchSummaryListModel CreateSummaryListModel(IEnumerable<RemittanceCenterBatchSummarizedModel> summaryModels)
{
var summaryModelList = new RemittanceCenterBatchSummaryListModel();
foreach (var summaryRec in summaryModels)
{
var summaryModel = new RemittanceCenterBatchSummarizedModel
{
FileId = summaryRec.FileId,
SourceFileName = summaryRec.SourceFileName,
BatchCode = summaryRec.BatchCode,
BatchType = summaryRec.BatchType,
DetailRecordCountAdc = summaryRec.DetailRecordCountAdc,
DetailRecordCountNotAdc = summaryRec.DetailRecordCountNotAdc,
AmountAdc = summaryRec.AmountAdc,
AmountNotAdc = summaryRec.AmountNotAdc,
UniqueFileCount = summaryRec.UniqueFileCount
};
summaryModelList.RemittanceBatchSummary.Add(summaryModel);
}
return summaryModelList;
}
Example input records:
Record1:
FileId: '123'
SourceFileName: 'test.file.txt'
BatchCode: 'aaa'
BatchType: 'scanned'
PaymentAmount: '50.00'
BillingSystemCode: 'Adc'
Record1:
FileId: '1234'
SourceFileName: 'test.file2.txt'
BatchCode: 'aab'
BatchType: 'scanned'
PaymentAmount: '52.00'
BillingSystemCode: 'Adc'
ActualOuput for UniqueFileCount Field:
UniqueFileCount = 1
ExpectedOutput results for UniqueFileCount Field:
UniqueFileCount = 2
What am I doing wrong?
It sounds like you want the distinct count of FileId for the entire collection and not just for each group, which will always be 1 since FileId is one of the fields you group on. If that is the case then you can just calculate that count first
int distinctFileIds = remittanceCenterSummaryListModel.RemittanceBatchSummaryRecor‌​d
.Select(x => x.FileId)
.Distinct()
.Count();
Then use that in your Linq query
UniqueFileCount = distinctFileIds

How to retrieve the couchbase view results using iteration?

This is my code for retrieving the list of comments from couchbase. The design document name is "Task" and the view name is: "GetComments".
public List<CommentsVO> GetComments(string TaskID, int LastCommentID, int totalCommentCount)
{
int startCount = LastCommentID - 1;
int endCount = startCount - 19;
int remainingCount = totalCommentCount - endCount;
if (endCount < 0)
{
endCount = 0;// totalCommentCount - remainingCount;
}
IView<CommentsVO> results = oCouchbase.GetView<CommentsVO>("Task", "GetComments");
results.StartKey(new object[] { TaskID, startCount }).EndKey(new object[] { TaskID, endCount });
if (results != null)
{
List<CommentsVO> resultlist = new List<CommentsVO>();
foreach (CommentsVO vo in results)//Here it is not entering inside the loop... Am i missing anything in this condition
{
resultlist.Add(vo);
}
resultlist.Reverse();
return resultlist;
}
return null;
}
My CommentsVo code is:
public class CommentsVO
{
public CommentsVO()
{
CommentedOn = Convert.ToString(DateTime.Now);
IsActive = "1";
}
[JsonIgnore]
public string TaskID { get; set; }
[JsonProperty("commented_user_id")]
public string CommentedUserID { get; set; }
[JsonProperty("commented_user_name")]
public string CommentedUserName { get; set; }
[JsonProperty("comment_description")]
public string CommentDescription { get; set; }
[JsonProperty("commented_on")]
public string CommentedOn { get; set; }
[JsonProperty("is_active")]
public string IsActive { get; set; }
[JsonProperty("seq")]
public string Sequence { get; set; }
}
My couchbase view code is:
function(doc) {
for(var i in doc.comments) {
emit([doc._id,doc.comments[i].seq],doc.comments[i]);
}
}
I have tried without using startkey and endkey its iterating but when i tried using startkey and endkey it is not entering inside the loop..
Kindly help me out..
When using a composite key, you would specify an array of keys in StartKey/EndKey. In your code, you're actually overwriting the keys with your second calls to StarKey and EndKey.
So something like:
results.StartKey(new object[] { TaskId, startCount }).EndKey(new object[] { TaskId, endCount });

Categories