How do I use Linq to query nested dynamic BsonDocuments? - c#

public class Foo
{
public ObjectId _id { get; set; }
public BsonDocument properties { get; set; }
}
public void FindFoos()
{
var client = new MongoClient(ConfigurationManager.ConnectionStrings["MongoDB"].ConnectionString);
var server = client.GetServer();
var db = server.GetDatabase("FooBar");
//var collection = db.GetCollection<GeoJsonFeature<GeoJson2DGeographicCoordinates>>("Sections");
var collection = db.GetCollection<Foo>("Foos");
collection.Insert(new Foo
{
properties = new BsonDocument{
{"Foo" , "foo1"},
{"Bar" , "bar1"}
}
});
collection.Insert(new Foo
{
properties = new BsonDocument{
{"Foo" , "foo2"},
{"Bar" , "bar2"}
}
});
var query = Query<Foo>.Where(foo => foo.properties.AsQueryable().Any(property => property.Name == "Foo" && property.Value.AsString == "foo1"));
var result = collection.Find(query).First();
}
calling FindFoos results in the following exception:
Unsupported where clause: Queryable.Any(Queryable.AsQueryable(foo.properties), (BsonElement property) => ((property.Name == "Foo") && (property.Value.AsString == "foo1"))).
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ArgumentException: Unsupported where clause: Queryable.Any(Queryable.AsQueryable(foo.properties), (BsonElement property) => ((property.Name == "Foo") && (property.Value.AsString == "foo1"))).
at the line:
var query = Query<Foo>.Where(foo => foo.properties.AsQueryable().Any(property => property.Name == "Foo" && property.Value.AsString == "foo1"));
I can do this query easily in the mongodb shell as:
db.Foos.find( {'properties.Foo' : 'foo1'} );
What is the correct way to do this query with Linq?

Try LINQ's SelectMany() method. It is used to flatten nested collections. Instead of using nested for loops, we can do the task in a more 'LINQ' way.
Ex given below -
Master m1 = new Master() { name = "A", lstObj = new List<obj> { new obj { i = 1, s = "C++" }, new obj { i = 1, s = "C#" }, new obj { i = 1, s = "Java" } } };
Master m2 = new Master() { name = "A", lstObj = new List<obj> { new obj { i = 4, s = "PHP" }, new obj { i = 5, s = "Ruby" }, new obj { i = 6, s = "Perl" } } };
List<Master> lstMasters = new List<Master> { m1, m2 };
var result = lstMasters.SelectMany(m => m.lstObj).Where(o => o.s == "PHP");
Just replace the Master class with your BsonDocument.

Related

ElasticSearch filtered query _search 400 error response

I am trying to use filter with search query. Search requset works correctly without filter. But using filter I get 400 error as response.
This is type mapping:
var mapp = new
{
mappings = new
{
posts = new
{
properties = new
{
FullText = new
{
type = "string",
analyzer = "russian"
},
Title = new
{
type = "string",
analyzer = "russian"
},
PostPubDate = new
{
type = "date"
},
Link = new
{
type = "string",
index = "not_analyzed"
},
RubricsIds = new
{
type = "integer"
},
ObjectsIds = new
{
type = "integer"
},
SourceId = new
{
type = "integer"
}
}
}
}
};
This is a request to index with filtered query:
string url = "http://localhost:9200/neg_collector/posts/_search";
var request = (HttpWebRequest)HttpWebRequest.Create(url);
var o = new
{
size = 20,
query = new
{
filtered = new
{
query = new
{
query_string = new
{
fields = new[] { "Title" },
query = search_query
}
},
filter = new
{
#bool = new
{
should = new
{
term = new
{
SourceId = sIds
}
}
}
}
}
}
};
request.Method = "POST";
var jsonObj = JsonConvert.SerializeObject(o);
var data = Encoding.UTF8.GetBytes(jsonObj);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
I want to use an array of integers to filter result with certain SourceId-s. But I got error 400.
What am I doing wrong? Thank you
So the problem was that this syntax was for elasticsearch 2 version (And it worked nice on another computer). Here I have ElasticSearch 5 and should use another was of filtering:
var o = new
{
size = 20,
query = new
{
#bool = new
{
must = new
{
query_string = new
{
fields = new[] { "Title" },
query = search_query
}
},
filter = new
{
terms = new
{
SourceId = new[] {10,11,12}
}
}
}
}
};
It is describerd HERE

LAMBDA C# union informations

Using C# with Lambda(or some method), how can I merge different informations(from columns) of the same intituition name ? They can have some common and some different fields.
See a example below:
Have you tried the Group By instruction ?
Here is an other stackoverflow about this : Group by in LINQ
{
List<Instituition> Instituitions = new List<Instituition>() {
new Instituition { Name = "Name1", Alias = "",Area="" },
new Instituition { Name = "Name1", Alias = "Alias1",Area="" },
new Instituition { Name = "name2", Alias = "Audi" ,Area="444"},
new Instituition { Name = "Name1", Alias = "",Area="Garden" }};
var results = Instituitions.GroupBy(i => i.Name,
i => i.Alias,
(key, g) => new
{
Name = key,
Alias = g.Where(a =>a != "").FirstOrDefault(),
Area = Instituitions.Where(a=>a.Name == key && a.Area != "").Select(a=>a.Area).FirstOrDefault()
}
);
}
class Instituition
{
internal string Name;
internal string Alias;
internal string Area;
}

MOQ Exception Was unhandled by user

I am pretty new to MOQ and I am in learning right now. I got task that I need to write unit test But I am getting the below error which I couldn't able to find. Please anyone help me with this. Also please review the code and give me some advises if my testcase needs changes.
Expection: IAcronisService.GetActivitiesFromDate("mygroup", 5/24/2016
8:33:34 PM) invocation failed with mock behavior Strict.....
for Save method(I have commented at save method where the exception has been thrown)
Process method calls save method
public int Process()
{
AcronisService = AcronisSvcManager.Get(ClientFactory, DataProviderFactory, LogAdapter);
DataObject backupGroupsDO = GetListOfAllCurrentGroups();
int activitiesSavedCount = Save(backupGroupsDO);
return activitiesSavedCount;
}
When I debug I also have seen the below line when I mouse over at first line on above process method. I thought service object is not calling/mocking. Is this anything to do with above exception? Please suggest some changes.
(IAcronisServiceProxy)AcronisService).AcronisURL threw a exception of type MOQ.MockException.
Save Method
private int Save(DataObject backupGroupsDO)
{
int count = 0;
foreach (DataRecord dr in backupGroupsDO.DataRecord)
{
BackupGroup backupGroup = new BackupGroup(dr);
// Get all activities for each group
AcronisClient.DataModel.Activity.ActivitiesResponse acronisActivities;
if (backupGroup.LastActivityDate == null)
{
// Get all activities for each group
***//Got Exception at this line***
acronisActivities = AcronisService.GetActivitiesFromDate(backupGroup.GroupName, DateTime.Now.AddDays(-90));
}
else
{
acronisActivities = AcronisService.GetActivitiesFromDate(backupGroup.GroupName, backupGroup.LastActivityDate);
}
if (acronisActivities == null || acronisActivities.Activities == null)
{
// Stop processing b/c might be an issue with the connection to Acronis
LogAdapter.LogError(KCBLog.Main, "Stopped processing activities, possible Acronis connection issue with getting Activities");
return -1;
}
var lastBackUpActivity = acronisActivities.Activities.OrderByDescending(z => z.StartTime).FirstOrDefault();
List<string> lastSuccessfulActivities = new List<string>();
List<string> lastActivities = new List<string>();
foreach (var acronisActivity in acronisActivities.Activities)
{
Kaseya.KCB.Common.DataModels.AcronisActivity activity = new AcronisActivity();
activity.BackupPlanId = acronisActivity.BackupPlanId;
activity.BytesProcessed = acronisActivity.BytesProcessed;
activity.BytesSaved = acronisActivity.BytesSaved;
activity.Cause = acronisActivity.CompletionResult == null ? null : acronisActivity.CompletionResult.Cause;
activity.Reason = acronisActivity.CompletionResult == null ? null : acronisActivity.CompletionResult.Reason;
activity.Effect = acronisActivity.CompletionResult == null ? null : acronisActivity.CompletionResult.Effect;
activity.DateCreated = DateTime.Now;
activity.FinishTime = acronisActivity.FinishTime;
activity.GroupId = backupGroup.Id;
activity.Id = acronisActivity.Id;
activity.InitiatedBy = acronisActivity.InitiatedBy;
activity.InstanceId = acronisActivity.InstanceId;
activity.IsRootActivity = (bool)acronisActivity.IsRootActivity;
activity.ParentActivityId = acronisActivity.ParentActivityId;
activity.PartitionId = PartitionId;
activity.StartTime = acronisActivity.StartTime;
activity.State = acronisActivity.State;
activity.Status = acronisActivity.Status;
activity.Title = acronisActivity.Title;
activity.UpdateTime = acronisActivity.UpdateTime;
AcronisActivityDataProvider.AddUpdateAcronisActivity(activity);
AcronisClient.DataModel.Activity.Activity lastSuccessfulActivity = acronisActivities.Activities.Where(z => z.Status == "ok" && z.Title.Contains("Running backup plan") && z.InstanceId==acronisActivity.InstanceId).OrderByDescending(z => z.FinishTime).FirstOrDefault();
var lastActivity = acronisActivities.Activities.Where(z => z.Title.Contains("Running backup plan") && z.InstanceId == acronisActivity.InstanceId).OrderByDescending(z => z.FinishTime).FirstOrDefault();
if (!string.IsNullOrEmpty(acronisActivity.InstanceId))
{
DataRecord assetDR = AssetDataProvider.GetByInstanceId(acronisActivity.InstanceId, PartitionId);
if (assetDR != null)
{
var assetId = assetDR.FindValue<string>("id", "");
if (lastSuccessfulActivity != null && !lastSuccessfulActivities.Contains(acronisActivity.InstanceId))
{
AssetDataProvider.UpdateLastSuccessfulActivityId(assetId, lastSuccessfulActivity.ParentActivityId);
lastSuccessfulActivities.Add(acronisActivity.InstanceId);
}
if (lastActivity != null && !lastActivities.Contains(acronisActivity.InstanceId))
{
AssetDataProvider.UpdateLastActivityId(assetId, lastActivity.ParentActivityId);
lastActivities.Add(acronisActivity.InstanceId);
}
}
}
count++;
}
if (acronisActivities.Activities != null && acronisActivities.Activities.Count>0)
{
//backupGroup.LastActivityDate = lastBackUpActivity.StartTime;
BackupGroupDataProvider.UpdateLastBackupGroupActivityDate(backupGroup.Id, lastBackUpActivity.StartTime);
}
}
return count;
}
Test Method I have writtern,
public void Test()
{
string groupName = "mygroup";
string mybackupAccountName = "mybackupaccount";
decimal PartitionId = 9m;
DateTime lastActivityDate = DateTime.Parse("2016-08-14T20:47:05");
string instanceId = "utinstanceId";
string assetId = "123";
DataRecord asset = new DataRecord();
asset.AddField("id", 123);
DataObject backupGroupsDO = new DataObject();
DataRecord groupDataRecord = new DataRecord();
groupDataRecord.AddField("id", 123);
groupDataRecord.AddField("partitionId", PartitionId);
groupDataRecord.AddField("groupName", groupName);
//groupDataRecord.AddField("lastActivityDate", lastActivityDate);
groupDataRecord.AddField("backupAccountName", mybackupAccountName);
backupGroupsDO.DataRecord.Add(groupDataRecord);
AcronisActivity acronisActivity = new AcronisActivity();
acronisActivity.BackupPlanId = "utBackupPlanId";
ActivitiesResponse activitiesResponse = new ActivitiesResponse();
AcronisClient.DataModel.Activity.Activity activity = new AcronisClient.DataModel.Activity.Activity();
activity.BackupPlanId = "utackupPlanId";
activity.BytesProcessed = 124674;
activity.BytesSaved = 06446;
activity.CompletionResult = new CompletionResult()
{
Cause = "utCause",
Reason = "utReason",
Effect = "utEffect"
};
activity.FinishTime = DateTime.Parse("2016-08-14T20:47:04");
activity.Id = "utId";
activity.InitiatedBy = "utInitiatedBy";
activity.InstanceId = "utInstanceId";
activity.IsRootActivity = true;
activity.ParentActivityId = "utParentActivityId";
activity.StartTime = DateTime.Parse("2016-08-14T20:47:02");
activity.State = "utState";
activity.Status = "utStatus";
activity.Title = "utTitle";
activity.UpdateTime = DateTime.Parse("2016-08-14T20:47:03");
activitiesResponse.Activities = new List<AcronisClient.DataModel.Activity.Activity>();
activitiesResponse.Activities.Add(activity);
var moqFactory = new MockRepository(MockBehavior.Strict);
var moqDataProviderFactory = moqFactory.Create<IDataProviderFactory>();
var moqDataProvider = moqFactory.Create<IDataProvider>();
var moqLogAdapter = moqFactory.Create<ILogAdapter>();
var moqAcronisServiceManager = moqFactory.Create<IAcronisServiceManager>();
var moqAcronisService = moqFactory.Create<IAcronisService>();
var moqAssetDataProvider = moqFactory.Create<IAssetDataProvider>();
var moqAcronisActivityDataProvider = moqFactory.Create<IAcronisActivityDataProvider>();
var moqBackupGroupDataProvider = moqFactory.Create<IBackupGroupDataProvider>();
Credential MSPCredential = new Credential();
moqDataProviderFactory.Setup(m => m.BackupGroupDataProvider.GetBackupGroups()).Returns(backupGroupsDO);
moqAcronisServiceManager.Setup(m => m.Get(It.IsAny<IRestClientFactory>(), It.IsAny<IDataProviderFactory>(), It.IsAny<ILogAdapter>(), "")).Returns(moqAcronisService.Object);
moqDataProvider.Setup(m => m.VerifyPartitionId(ref PartitionId));
moqDataProvider.Setup(m => m.ExecuteNonQuery(It.IsAny<AddUpdateAcronisActivity>())).Returns(1);
moqAcronisService.Setup(m => m.GetActivitiesFromDate(groupName, lastActivityDate)).Returns(activitiesResponse);
moqAcronisActivityDataProvider.Setup(m => m.AddUpdateAcronisActivity(acronisActivity));
moqAssetDataProvider.Setup(m => m.GetByInstanceId(instanceId, PartitionId,1)).Returns(asset);
moqAssetDataProvider.Setup(m => m.UpdateLastActivityId(assetId, activity.ParentActivityId));
moqAssetDataProvider.Setup(m => m.UpdateLastSuccessfulActivityId(assetId, activity.ParentActivityId));
moqBackupGroupDataProvider.Setup(m => m.UpdateLastBackupGroupActivityDate("1234", lastActivityDate));
// moqAcronisService.Setup(m => m.GetActivitiesFromDate(groupName, Convert.ToDateTime("2016-08-18T13:18:40.000Z"))).Returns(activitiesResponse);
ActivityHarvester activityHarvester = new ActivityHarvester();
activityHarvester.PartitionId = PartitionId;
activityHarvester.DataProvider = moqDataProvider.Object;
activityHarvester.LogAdapter = moqLogAdapter.Object;
activityHarvester.AcronisSvcManager = moqAcronisServiceManager.Object;
activityHarvester.DataProviderFactory = moqDataProviderFactory.Object;
activityHarvester.AcronisService = moqAcronisService.Object;
activityHarvester.AssetDataProvider = moqAssetDataProvider.Object;
activityHarvester.BackupGroupDataProvider = moqBackupGroupDataProvider.Object;
activityHarvester.AcronisActivityDataProvider = moqAcronisActivityDataProvider.Object;
activityHarvester.process();//*process method calls above save method method*
moqFactory.VerifyAll();
}
From your example, your setup for IAcronisService.GetActivitiesFromDate shows that it is expecting lastActivityDate of 2016-08-14T20:47:05 based on the code but the error shows that you used a different date 5/24/2016 8:33:34 PM than expected. As the moq behavior is Strict, this
Causes the mock to always throw an exception for invocations that don't have a corresponding setup.
You can make the setup a little more flexible by using It.IsAny<DateTime>()
moqAcronisService
.Setup(m => m.GetActivitiesFromDate(groupName, It.IsAny<DateTime>()))
.Returns(activitiesResponse);
or changing the behavior in your moq factory to use Default or Loose MockBehavior.

How i can add Couchbase Documents in a list?

I'm experimenting with Couchbase + Xamarin.Forms trying to do a simple search, showing the results in a ListView but I've stuck. :(
Someone know how to add the rows/documents of a query in a list?
public List<Visitor> SearchRecord (string word)
{
var viewByName = db.GetView ("ByName");
viewByName.SetMap((doc, emit) => {
emit (new object[] {doc["first_name"], doc["last_name"]}, doc);
}, "2");
var visitorQuery = viewByName.CreateQuery();
visitorQuery.StartKey = new List<object> {word};
// visitorQuery.EndKey = new List<object> {word, new Dictionary<string, object>()};
visitorQuery.Limit = 100;
var visitors = visitorQuery.Run();
var visitorList = new List<Visitor> ();
foreach (var visitor in visitors) {
// visitorList.Add(visitor.Document); <-- Error.
System.Console.WriteLine(visitor.Key);
}
return visitorList;
}
I get the error messages:
Error CS1501: No overload for method Add' takes2' arguments
(CS1501) (Demo_Couchbase.Droid) Error CS1502: The best overloaded
method match for
System.Collections.Generic.List<Demo_Couchbase.Visitor>.Add(Demo_Couchbase.Visitor)'
has some invalid arguments (CS1502) (RegistroAgil_Couchbase.Droid)
Error CS1503: Argument#1' cannot convert Couchbase.Lite.Document'
expression to typeDemo_Couchbase.Visitor' (CS1503)
(Demo_Couchbase.Droid)
Thank you in advance for any help you can provide.
There is problem in your mapping part. You can directly cast documents on GetView.
You can try bellow code.
public List<Visitor> SearchRecord (string word)
{
var viewByName = db.GetView<Visitor>("ByName","ByName");
var visitorQuery = viewByName.CreateQuery();
visitorQuery.StartKey = new List<object> {word};
visitorQuery.Limit = 100;
var visitors = visitorQuery.Run();
var visitorList = new List<Visitor> ();
foreach (var visitor in visitors) {
visitorList.Add(visitor.Document);
System.Console.WriteLine(visitor.Key);
}
return visitorList;
}
I don't know if this is the most elegant solution though but my code works fine now.
Visitor ToRecord(Document d) {
var props = d.Properties;
return new Visitor {
Id = props["_id"].ToString(),
FirstName = (string)props["first_name"],
LastName = (string)props["last_name"],
Occupation = (string)props["occupation"],
Company = (string)props["company"],
Email = (string)props["email"],
Phone = (string)props["phone"],
Birthday = (string)props["birthday"],
LastVisit = (string)props["last_visit"],
LocalImagePath = (string)props["local_image_path"],
Type = (string)props["type"],
CreatedAt = (string)props["created_at"],
UpdatedAt = (string)props["updated_at"],
DeletedAt = (string)props["deleted_at"]
};
}
public List<Visitor> SearchRecord (string word)
{
var viewByName = db.GetView ("ByName");
viewByName.SetMap((doc, emit) => {
if ((doc.ContainsKey("type") && doc["type"].ToString() == "visitor") && (doc.ContainsKey("deleted_at") && doc["deleted_at"] == null))
emit (new [] {doc["first_name"], doc["last_name"]}, doc);
}, "2");
var visitorQuery = viewByName.CreateQuery();
visitorQuery.StartKey = word;
visitorQuery.Limit = 50;
var rows = visitorQuery.Run();
var visitorList = new List<Visitor> ();
for (int i = 0; i < rows.Count (); i++) {
var row = rows.GetRow (i);
var name = row.Document.GetProperty ("first_name").ToString ().ToLower () + " " + row.Document.GetProperty ("last_name").ToString ().ToLower ();
if (name.Contains (word))
visitorList.Add(ToRecord(row.Document));
}
return visitorList;
}

IQueryable, converting Anonymous Type to Strong Type

Is there a more elegant/concise way of this; I'd like to get rid of foreach loop with the WorkListItem initialization code.
var queryable = registrations.Select(
r => new
{
r.Id, r.AccountNumber, r.DateAdded, r.DateUpdated, r.Patient, r.Patient.InsuranceInfos
});
var list = queryable.ToList();
var workListItems = new List<WorkListItem>();
foreach (var anonymous in list)
{
var w = new WorkListItem
{
Id = anonymous.Id,
ClientAccountId = anonymous.AccountNumber,
DateAdded = anonymous.DateAdded,
DateUpdated = anonymous.DateUpdated,
Patient = anonymous.Patient,
InsuraceInfos = anonymous.Patient.InsuranceInfos
};
workListItems.Add(w);
}
return workListItems;
Yes you can completely cut out the "middle-man" as it were and select straight into a new WorkListItem as below:
var list = registrations.Select(r => new WorkListItem
{
Id = r.Id,
ClientAccountId = r.AccountNumber,
DateAdded = r.DateAdded,
DateUpdated = r.DateUpdated,
Patient = r.Patient,
InsuraceInfos = r.Patient.InsuranceInfos
}).ToList();

Categories