Solrnet index data post object list - c#

I use solrnet to index data like below :
var solrFacility = new SolrNetFacility("http://mysolr:8983/solr/testcollection");
var container = new WindsorContainer();
container.AddFacility("solr", solrFacility);
var solr = container.Resolve<ISolrOperations<Dictionary<string, object>>>();
solr.Add(new Dictionary<string, object> {
{"id", "http://google.com/link1"},
{"title", "test.pdf"},
{"content", "abcdefghijk"},
{"author", "Ziv Hsu"},
{"editor", "Ziv Hsu"},
});
solr.Commit();
It's work;
but if I have a object list need to index
is not work it'll get 400 code like below:
public class LSchemaField
{
public List<SchemaField> SchemaFieldList = new List<SchemaField>();
}
public class SchemaField
{
public virtual string id { get; set; }
.....
}
LSchemaField SchemaFieldList = new LSchemaField();
SchemaField SchemaFields = new SchemaField();
SchemaFields.id = ....;
SchemaFieldList.SchemaFieldList.Add(SchemaFields);
SchemaField SchemaFields2 = new SchemaField();
SchemaFields2.id =....;
SchemaFieldList.SchemaFieldList.Add(SchemaFields2);
var solrFacility = new SolrNetFacility("http://mysolr:8983/solr/testcollection");
var container = new WindsorContainer();
container.AddFacility("solr", solrFacility);
var solr = ObjectFactory.GetInstance<ISolrOperations<LSchemaField>>();enter code here
solr.Add(SchemaFieldList );
solr.Commit();
Can it add a object list?

In SchemaField class you need to set SchemaField attribute for each property which you want to add in solr.this will map properties to solr fileds.
https://github.com/mausch/SolrNet/blob/master/Documentation/Mapping.md

Related

Create new list of objects for each of the item in another object list using Linq

I have an object with
public class test
{
public object obj1;
public List<string> items;
}
I have a List<test>. For each of the items i want to create a new object with properties from obj1 and an item. The items list can be null or empty. Is there a way to do in Linq?
List<test> tests = new List<test>();
var ob1=new test{ obj1 = "obj1" };
var ob2=new test{ obj1 = "obj2" };
var ob3=new test{ obj1 = "obj3" };
var ob4=new test{ obj1 = null };
tests.Add(ob1);
tests.Add(ob2);
tests.Add(ob3);
tests.Add(ob4);
var result = tests.Select(e => new NewType
{
name = e.obj1 != null ? e.obj1.ToString() : null
});
foreach (var item in result)
{
Console.WriteLine(item.name);
}
Is this what you are looking for?
Say Test.Obj1 has two properties you want to include in each new item, 'Name' & 'ID', along with an item from the list - try a query like this.
Will generate a list of new (anonymous) objects with (for example) the first element of each Test.Obj1.List
IEnumerable<dynamic> results = tests
.Select(o => new { Name = o.obj1.Name,
ID = o.obj1.Id,
Item = o.items.First() ?? null} )
.ToList();
Console.WriteLine(results.ElementAt(0));
Console.WriteLine(results.ElementAt(1));
Console.WriteLine(results.ElementAt(2));
// { Name = Foo, ID = 1, Item = a }
// { Name = Bar, ID = 2, Item = d }
// { Name = Goo, ID = 3, Item = g }
// Example types below...
public class Obj1
{
public string Name {get; set;}
public int Id {get; set;}
public Obj1(string name, int id)
{
Name = name;
Id = id;
}
}
// Create some instances
Obj1 objA = new MyObject("Foo", 1);
Obj1 objB = new MyObject("Bar", 2);
Obj1 objC = new MyObject("Goo", 3);
// Your test class that contains the custom object, and a list
public class Test
{
public Obj1 obj1;
public List<string> items;
public Test(Obj1 myobject, List<string> myItems)
{
obj1 = myobject;
items = myItems;
}
}
// Make a list of test objects
List<Test> tests = new List<Test>{
new Test(objA, new List<string>{"a", "b", "c"}),
new Test(objB, new List<string>{"d", "e", "f"}),
new Test(objC, new List<string>{"g", "h", "i"})};
For new{}, you can replace with a named type T and constructor as needed and update the results list to be
IEnumerable<T>
Also, you may have a specific criteria for which item in the list you want (or all) so you could add a more interesting query in the constructor rather than .First()
Or to just grab the whole test item adjust the constructor as
new { Obj = o.obj1, Items = o.items}
Hope this helps - there are some great links in this collection: https://learn.microsoft.com/en-us/dotnet/csharp/linq/perform-a-subquery-on-a-grouping-operation

Define list of objects. Get by specific field in object

How can we create a list of objects in C# and acces them by a specific field inside this object?
For example take this object:
class Section
{
public string Name { get; }
public long Size { get; }
public Section(string name, long size)
{
Name = name;
Size = size;
}
}
I would like to create a list of these objects which I can access by Section.Name.
I can create a dictionary like:
private static readonly Dictionary<string, Section> validSections = new Dictionary<string, Section>
{
{ "section-a", new Section("section-a", 1) },
{ "section-b", new Section("section-b", 2) },
{ "section-c", new Section("section-c", 3) },
{ "section-d", new Section("section-d", 4) },
};
But as you see, I have to declare the section name twice, which looks inelegant. Is there a more elegant way?
But as you see, I have to declare the section name twice, which looks
inelegant. Is there a more elegant way?
To avoid repetitve typing you can create dictionary from collection of sections via ToDictionary call:
private static readonly Dictionary<string, Section> validSections = new[] {
new Section("section-a", 1),
new Section("section-b", 2),
new Section("section-c", 3),
new Section("section-d", 4)
}.ToDictionary(s => s.Name);
If this is not time critical then you can use List<Section> list = new ArrayList<Section>(); and store data in it.
Later you can use LINQ to query based on name .where(x=>x.Name=="somename")
First of all your Model class can look like:
class Section
{
public string Name { get; set; }
public long Size { get; set; }
}
You don't need the Name twice so you can just create a list:
private static List<Section> myList = new List<Section>();
myList.add(new Section {Name = "section-a", Size = 1});
// do this for all the sections ...
Then as other answers suggest you can use LINQ:
myList.Single(s => s.Name == "section-a");
Will simply return the single element where the name is "section-a".
Read more about LINQ here: https://msdn.microsoft.com/en-us/library/bb308959.aspx
You could write a function that takes a list of sections and returns the corresponding dictionary. Something like:
public static Dictionary<string, Section> SectionDictionary(List<Section> sections) {
var dict = new Dictionary<string, Section>();
foreach (var section in sections)
dict.Add(section.Name, section);
return dict;
}
You can just access the elements using LINQ:
var list = ...;
var el = list.FirstOrDefault(o => o.Name = nameValue);
Or you can create a (collection) class that implements your own indexer / getter logic. E.g. (pseudocode)
public class MyCollection : Collection<Section>
{
public Section this[string nameValue]
{
get
{
return this.FirstOrDefault(o => o.Name == nameValue);
}
}
}
Then the usage is:
var coll = new MyCollection() ....;
var el = coll["Some name"];

Unit test won't "cover" simple get method. (c#)

I have a simple "Get" method. Ex:
public class Foo : IFoo
{
public Dictionary<string,string> GetSomething(string xyz)
{
var result = new Dictionary<string,string>
... Go to DB and return some key value pairs
return result;
}
}
I wrote a simple test that execute and passes successfully but I'm not getting code coverage on the method.
[TestMethod()]
public void GetSomething()
{
var target = new StubIFoo();
var expected = new Dictionary<string, string>
{
{"blahKey","blahValue"}
};
var results = target.GetSomethingString = s =>
{
var result = new Dictionary<string, string> {{"a", "b"}};
return result;
};
var actual = results("a");
CollectionAssert.AreEqual(expected,actual);
}
I also tried to target the class itself, which provides the coverage but doesn't return any results (ex: "var target = new StubFoo();")
Again, it successfully executes and passes but I'm not getting any coverage. Any pointers would be appreciated. Thanks.
Foo.GetSomething() has 0 code coverage, because you never call it in your test.
Instead, you call StubIFoo.GetSomething().
Change var target = new StubIFoo(); into var target = new Foo();, remove the code initializing StubIFoo and you will get some coverage.
Stubs are there to prevent you from using (and testing) the real class. But you must not use a stub of the class you are testing !
In your test you are not calling the method GetSomething, but instead are setting a value to the property GetSomethingString.
// Here is the problem. This:
var results = target.GetSomethingString = s =>
{
var result = new Dictionary<string, string> {{"a", "b"}};
return result;
};
// Is equal to this:
var lambda = s =>
{
var result = new Dictionary<string, string> {{"a", "b"}};
return result;
};
var results2 = target.GetSomethingString = lambda;
Here is general idea what you should do
public class Foo : IFoo
{
IDbAccess db;
// Pass the interface, do pass parameters to create it inside constructor
public Foo(IDbAccess db)
{
this.db = db;
}
public Dictionary<string,string> GetSomething(string xyz)
{
var result = new Dictionary<string,string>
// ... Go to DB and return some key value pairs
result.Add(db.MethodWhatever(xyz));
return result;
}
}
[TestMethod()]
public void GetSomething()
{
var dbMock = new DatabaseMock(); // This implements IDbAccess
var target = new Foo(dbMock);
var expected = new Dictionary<string, string>
{
{"blahKey","blahValue"}
};
// get something
var results = target.GetSomething("xyzstring");
// verify results
var actual = results.whatever;
CollectionAssert.AreEqual(expected,actual);
}

C# Facebook SDK dynamic data conversion

I got an Object from Facebook SDK
var responsePages = (JsonObject)FBClient_.Get(new { ids =
[123123123, 123123123, 12312213, etc]});
This query returns data (see image)
Now how do I convert this into a list of objects?
I have tried following but it does not work
var pe = (from dynamic page
in (IList<object>)(object)responsePages.Values
orderby page.name ascending
select new FBPage
{
Id = Convert.ToString(page.id),
}
).ToList();
So that failed, would appreciate any help because this dynamic stuff drives me seriously mad.
Thanks
You don't need to cast if you are using dynamic.
var fb = new FacebookClient();
dynamic result = fb.Get(new { ids = new[] { "...", "..." } });
var pages = new List<FBPage>();
foreach (var page in result.Values)
{
var fbPage = new FBPage {
Id = page.id,
Name = page.name
};
pages.Add(fbPage);
}
or if you want to use linq. (extension methods are not supported for dynamic, so you will need to do some casting, JsonObject => IDictionary<string, dyanmic>, JsonArray => IList<dynamic>)
var pages = ((IDictionary<string, dynamic>)result)
.Select(kpv => kpv.Value)
.Select(p => new FBPage { id = p.id, name = p.name })
.ToList();
Or you strongly typed classes.
var fbPages = fb.Get<IDictionary<string, FBPage>>(new {
ids = new[] { "...", "..." }
}).Values;
public class FBPage
{
public string id { get; set; }
public string name { get; set; }
}
'responsePages.Values' is an ICollection<JsonValue>
JsonValues can be serialized to Json strings, which can then be made the play things of a good Json deserializer such as Json.Net.
Using a simple loop this might look something like:
List<dynamic> dynamicList = new List<dynamic>();
List<FBPage> pe = new List<FBPage>();
foreach(var page in responsePages.Values)
{
//ToString is overridden in JsonValue to provide a string in Json format
string pageAsJsonString = page.ToString();
//Deserialize (parse) to a dynamic object using Json.Net's JObject.Parse static method
dynamic parsedPage = JObject.Parse(pageAsJsonString);
dynamicList.Add(parsedPage);
//Alternatively, if you have an appropriate object handy, deserialize directly:
FBPage deserializedPage = JsonConvert.DeserializeObject<FBPage>(pageAsJsonString);
pe.Add(deserializedPage);
}
foreach(dynamic page in dynamicList)
{
Console.WriteLine(page.name);
}
foreach(FBPage page in pe)
{
Console.WriteLine(page.Id);
}

Refactoring WPF code behind

I have a method called get Data which executes my SQL and returns some rows of ContactLists containing Aggregated Labels.At the moment this method is in my code behind and would like to move it to a separate Data Access class. I would appreciate your assistance. Thanks!
Is normal, if i understand your code, you do this operation after ContactList initialization:
contactList.Labels = new ObservableCollection<Label>()
{
new Label() {
Name = dr["LABEL_NAME"].ToString(),
Count = Convert.ToInt32(dr["LABEL_COUNT"])
}
};
For each ContactList is always added one item, you will do something like this:
contactList.Labels = new ObservableCollection<Label>();
foreach(var item in <yourLabelDataSource>)
contactList.Labels.Add(new Label(...));
The solution is like this:
Dictionary<int, ContactList> myContactDictionary = new Dictionary<int, ContactList>();
using (DB2DataReader dr = command.ExecuteReader())
{
while (dr.Read())
{
int id = Convert.ToInt32(dr["CONTACT_LIST_ID"]);
if (!myContactDictionary.ContainsKey(id))
{
ContactList contactList = new ContactList();
contactList.ContactListID = id;
contactList.ContactListName = dr["CONTACT_LIST_NAME"].ToString();
contactList.Labels = new ObservableCollection<Label>()
{
new Label()
{
Name = dr["LABEL_NAME"].ToString(),
Count = Convert.ToInt32(dr["LABEL_COUNT"])
}
};
myContactDictionary.Add(id, contactList);
}
else
{
//Add new label because CONTACT_LIST_ID Exists
ContactList contactList = myContactDictionary[id];
contactList.Labels.Add(
new Label()
{
Name = dr["LABEL_NAME"].ToString(),
Count = Convert.ToInt32(dr["LABEL_COUNT"])
}
);
}
}
}
Ben, for your last question you can use this solution:
else
{
//Add new label because CONTACT_LIST_ID Exists
ContactList contactList = myContactDictionary[id];
string name = dr["LABEL_NAME"].ToString();
var label = contactList.Labels.Where(l => l.Name == name).FirstOrDefault();
if( label != null )
label.Count += Convert.ToInt32(dr["LABEL_COUNT"]);
else
{
contactList.Labels.Add(
new Label()
{
Name = dr["LABEL_NAME"].ToString(),
Count = Convert.ToInt32(dr["LABEL_COUNT"])
}
);
}
I hope this code is readable and helpfulL!
}
This is other response:
Create and Object Model that can contain your required data:
public class DataResult
{
public ObservableCollection<AggregatedLabel> AggregatedLabels { get; set; }
public ObservableCollection<ContactList> ContactLists { get; set; }
}
You can build a method that return DataResult object, in your method (GetData()), you can valorize the two different properties (AggregatedLabels and ContactsList) with your DB Result. In the and you can return DataResult Object.
A little example here:
public DataResult GetData()
{
DataResult result = new DataResult();
result.AggregatedLabels = new ObservableCollection<AggregatedLabel>();
result.ContactLists = new ObservableCollection<ContactList>();
// Manipulate data result with your method logic like in this examle:
foreach(var something in dbResult)
{
ContactList cl = new ContactList() {
//Binding from something
}
result.ContactLists.Add(cl);
}
return result; //return your Object Model with required Data!
}
I hope it is conceptually clear

Categories