Q1. How to use Solrnet to search multiple collection?
Q2. I created a method to add data to Solr,
And if i want to dynamic assign sechma add data to Solr,
how to modify it?
public void SolrFeeder(SchemaFieldList DataList)
{
var solrFacility = new SolrNetFacility(SolrServer);
var container = new WindsorContainer();
container.AddFacility("solr", solrFacility);
var solr = container.Resolve<ISolrOperations<SchemaField>>();
foreach (var item in DataList.SchemaFieldList)
{
solr.Add(item);
}
solr.Commit();
}
The standard syntax for searching across collections is to provide the name of the collections in the query - i.e. if you're querying collection1, you can still append a parameter named collection which contains a list of the collections you want to search, collection=collection1,collection2,collection3.
You can use the syntax for "Additional Parameters" in SolrNet to add custom arguments to a query:
ISolrOperations<Product> solr = ...
var products = solr.Query(SolrQuery.All, new QueryOptions {
ExtraParams = new Dictionary<string, string> {
{"collection", "collection1,collection2,collection3"}
}
});
Related
I have a list of strings in C# and I want to loop through the list and add each item of the list as a property of my class.
For eg:
public class test
{
List<string> inputList = new List<string> {"add", "subtract", "multiply"};
foreach(var val in inputList)
{
//code to convert string to property
}
}
After I run the above code, when I create a new object of class test, I would like to get:
test.add or test.subtract etc. and I should be able to assign values to these properties.
Is this possible? If yes, could someone please suggest the best way of doing this?
Continuing from above, the aim here is to add API.
The list here is dynamically loaded. I should have started with a more apt list as an example.
public class test
{
List<string> inputList = new List<string> {"name", "age", "dob"};
foreach(var val in inputList)
{
//code to convert string to property of the class test
}
}
After the code is run I should be able to assign values to name, age and dob as user inputs i.e
test.name = "blah"
test.age = "123"
Since the list is dynamically updated, the items (and their number) in the list will vary. All the items in the list have to be added as a property of the class test and the user should be able to assign values to those properties at run time.
You can use dynamic to achieve this. While it's very good to be aware of the concept of dynamic and how to use it, it kills the benefits of using a strongly typed language and compile time checking, and should really only be used when the alternative is more painful:
List<string> inputList = new List<string> {"add", "subtract", "multiply"};
var builder = new System.Dynamic.ExpandoObject() as IDictionary<string, Object>;
foreach(var val in inputList)
{
builder.Add(val, $"{val}: some value here");
}
var output = (dynamic)builder;
Console.WriteLine(output.add);
Console.WriteLine(output.subtract);
Console.WriteLine(output.multiply);
I need to read certain fields in documents from Mongo. I filtered out a document using the Filter.EQ() method but how can I find and store a field in that document? This is my code:
public void human_radioButton_Checked(object sender, RoutedEventArgs e)
{
Upload human = new Upload(); //opens connection to the database and collection
var filter = Builders<BsonDocument>.Filter.Eq("name", "Human");
race_desc description = new race_desc();
description.desc = Convert.ToString(filter);
desc_textBox.Text = description.desc;
However, this doesn't work since I didn't grab any fields, just the document. So how can I read a field called 'A' and store it into an object?
Thanks
When you define a filter using the Builders<BsonDocument>.Filter here, you merely define a filter that you can use/execute in a query. Much like storing a SQL string in a string variable.
What you missed here is executing the filter and actually retrieve the data. According to Mongodb C# driver doc:
var collection = _database.GetCollection<BsonDocument>("restaurants");
var filter = Builders<BsonDocument>.Filter.Eq("borough", "Manhattan");
var result = await collection.Find(filter).ToListAsync();
Then you can iterate the results and access the properties like
foreach(var result in results)
{
//do something here with result.your_property
}
And if you just want the first of the result
var result = (await collection.Find(filter).ToListAsync()).FirstOrDefault();
Now if you want to cast the BsonDocument you got now to your own class deserialize document using BsonSerializer:
var myObj = BsonSerializer.Deserialize<YourType>(result);
You can also map it to your own class:
var yourClass = new YourType();
yourClass.Stuff= result["Stuff"].ToString();
I'm setting up a Web API project that uses Azure Push Notifications. I'd like to use the new "Installation" model instead of the older "Registration" model. The documentation is a bit limited however.
Looking at MSDN, Microsoft.Azure.NotificationHubs.Installation has a Tags property.
There is also has a Templates property. The template type is InstallationTemplate and surprisingly also has Tags.
The templates are not just a list but a dictionary that maps from string to InstallationTemplate.
I understand the idea behind tags. But I'm confused about the two tag properties and the key of the dictionary.
I saw an example where the Installation.Tagis set to "foo" and then two templates are added with the keys "template1" and "template2". The InstallationTemplate.Tag was set to "tag-for-template1" and "tag-for-template2".
Do the two tag values have to match?
What is each of them used for?
What should the key of the template dictionary be?
If I use the method to send a notification via the NotificationHubClient, I can specify a tag - what is it matched against and which template will be picked?
After some testing I'm a bit wiser.
Both, the Microsoft.Azure.NotificationHubs.Installation's tags and the tags inside of the InstallationTemplate will be evaluated when using SendTemplateNotificationAsync(). The key that has to be specified in the dictionary seems to be unused.
Example:
var installationA = new Installation();
installationA.Tags = new List<string> { $"install-a" };
installationA.Templates.Add("someKey", new InstallationTemplate
{
Body = "JSON-FOR-TEMPLATE"
Tags = new List<string> { $"subtemplate1" }
});
installationA.Templates.Add("someOtherKey", new InstallationTemplate
{
Body = "JSON-FOR-TEMPLATE"
Tags = new List<string> { $"subtemplate2" }
});
var installationB = new Installation();
installationB.Tags = new List<string> { $"install-b" };
installationB.Templates.Add("someKey", new InstallationTemplate
{
Body = "JSON-FOR-TEMPLATE"
Tags = new List<string> { $"subtemplate1" }
});
installationB.Templates.Add("someOtherKey", new InstallationTemplate
{
Body = "JSON-FOR-TEMPLATE"
Tags = new List<string> { $"subtemplate2" }
});
Using tag expressions you can now filter for any combination of "install-a", "install-b", "subtemplate1" and "subtemplate2".
The keys "someKey" and "someOtherKey" will not be used by the query and I don't understand why they did not use a List<T> instead of the dictionary.
I am developing a console application to extract data from a SharePoint 2013 server using the .NET client object model of the SharePoint Server 2013 Client Components SDK:
using (var clientContext = new ClientContext(SharePointUrl))
{
var list = clientContext.Web.Lists.GetByTitle(listName);
var camlQuery = CamlQuery.CreateAllItemsQuery();
var listItems = list.GetItems(camlQuery);
clientContext.Load(listItems, GetFields(fields));
clientContext.ExecuteQuery();
return listItems.ToList();
}
This is the GetFields() method I call to construct the list of fields I request:
private Expression<Func<ListItemCollection, object>>[] GetFields(IEnumerable<string> fields)
{
return fields
.Select(field => (Expression<Func<ListItemCollection, object>>)(items => items.Include(item => item[field])))
.ToArray();
}
There is one big list -- "Demands" -- that is giving me troubles for some User-type fields: whenever I include these as a field that needs to be retrieved via the GetFields() method (see above), I get the infamous "Value does not fall within the expected range." error. For instance, "DTBusinessResponsible" can be retrieved, yet "DTSupplyLeadResponsible" cannot.
I have been informed that "Demands" contains two ContentTypes: "Demand" and "I-Demand". The fields that are giving me issues are exclusive to "I-Demand".
I cannot figure out how I can retrieve these problematic fields. I've tried retrieving the ContentTypes for "Demand" and "I-Demand" and adding them to list:
var demandContentType = clientContext.Web.ContentTypes.GetById(contentTypeByName["Demand"]);
var iDemandContentType = clientContext.Web.ContentTypes.GetById(contentTypeByName["I-Demand"]);
list.ContentTypesEnabled = true;
list.ContentTypes.AddExistingContentType(demandContentType);
list.ContentTypes.AddExistingContentType(iDemandContentType);
But this is no use, I get an error telling me both ContentTypes are already present.
(Note that I have already asked this over at the SharePoint SE, but I didn't get any useful responses there.)
EDIT: Let's simplify the question.
I need to retrieve a number of fields from a SharePoint List called "Demands". To that end, I add the fields I require as Expression<Func<T, object>>[].
However, some of the fields I need to retrieve are exclusive to "I-Demand", which is one of the ContentTypes of the "Demands" list. Whenever I add those fields, the query crashes and produces the infamous "Value does not fall within the expected range." error. I have no trouble retrieving dozens of other fields which are all part of the "Demand" content type.
How can I retrieve those fields that are exclusive to the "I-Demand" content type?
EDIT: Here's what doesn't work...
var fields = new List<string>
{
"DTBusinessRequestor",
"DTBusinessResponsible",
"DTBusinessSponsor",
"DTDemandAccountable",
"DTIICTBusinessAnalyst",
"DTSupplyAccountable",
"DTSupplyLeadResponsible",
"Title",
"Author",
"Created",
"Editor",
"Modified",
"ID"
};
var viewXml = new StringBuilder();
viewXml.AppendLine("<ViewFields>");
foreach (var field in fields)
{
viewXml.AppendFormat("<FieldRef Name=\"{0}\" />", field).AppendLine();
}
viewXml.AppendLine("</ViewFields>");
var camlQuery = new CamlQuery { ViewXml = string.Format("<View>{0}</View>", viewXml) };
List<ListItem> results;
using (var clientContext = GetClientContext())
{
var list = clientContext.Web.Lists.GetByTitle("Demands");
var listItems = list.GetItems(camlQuery);
clientContext.Load(listItems);
clientContext.ExecuteQuery();
results = listItems.ToList();
}
var validNames = new HashSet<string>();
foreach (var listItem in results)
{
foreach (var field in fields)
{
object value;
if (!listItem.FieldValues.TryGetValue(field, out value))
continue;
if (value != null)
{
validNames.Add(field);
}
}
}
When I execute the above code:
results contains 10 (ten) items while there are 160 entries in SharePoint;
validNames contains six fields: "Title", "Author", "Created", "Editor", "Modified", "ID".
Which is a slightly better result than the one I had, since "Author" and "Editor" were problematic. The rest of the fields return null, but that could be because the ten results do not have values. However, I cannot compare to the values in SharePoint since the ten titles that are returned are not ones that are found in the Demands table...
I try to filter by ContentType by adding this line after viewXml.AppendLine("</ViewFields>");:
viewXml.AppendLine("<Query><Where><Eq><FieldRef Name='ContentType' /><Value Type='Computed'>I-Demand</Value></Eq></Where></Query>");
Result: results contains no entries.
I remove the filter by ContentType and change this:
var camlQuery = new CamlQuery { ViewXml = string.Format("<View>{0}</View>", viewXml) };
to this:
var camlQuery = CamlQuery.CreateAllItemsQuery();
camlQuery.ViewXml = string.Format("<View>{0}</View>", viewXml);
Same result as originally: ten items, same fields.
I then remove this line:
camlQuery.ViewXml = string.Format("<View>{0}</View>", viewXml);
Result: 160 items, values for "DTBusinessRequestor", "DTBusinessResponsible", "DTBusinessSponsor" and "DTIICTBusinessAnalyst" BUT no results for "Author" and "Editor" -- so I'm back where I started.
I have not found a single solution where it returns me values for all 160 entries in the Demands list combined with values for "Author" and "Editor" and also "DTDemandAccountable", "DTSupplyAccountable" and "DTSupplyLeadResponsible" (where applicable).
Whenever I add <Query><Where><Eq><FieldRef Name='ContentType' /><Value Type='Computed'>I-Demand</Value></Eq></Where></Query> I get zero results.
Construct two separate caml queries, each specifying one or the other content type. Then, take the results, and read them into your own data objects (e.g. POCO objects -- Plain Old C# Objects). Once they are in your Poco data objects, you can use Linq to merge the datasets, which you can then consume.
You can write generic methods to read the ListItem data into POCO objects, so this can be a reusable approach to use whenever you encounter this issue.
Through much trial and error, I have managed to get this to work:
var fields = new List<string>
{
"DTSupplyAccountable",
"DTSupplyLeadResponsible",
"Author",
"Editor",
"ID"
};
var viewXml = new StringBuilder();
viewXml.AppendLine("<ViewFields>");
foreach (var field in fields)
{
viewXml.AppendFormat("<FieldRef Name=\"{0}\" />", field).AppendLine();
}
viewXml.AppendLine("</ViewFields>");
viewXml.AppendLine("<Query><Where><Eq><FieldRef Name=\"ContentType\" /><Value Type=\"Computed\">I-Demand</Value></Eq></Where></Query>");
var camlQuery = new CamlQuery {ViewXml = string.Format("<View Scope=\"RecursiveAll\">{0}</View>", viewXml)};
List<ListItem> results;
using (var clientContext = GetClientContext())
{
var list = clientContext.Web.Lists.GetByTitle("Demands");
var listItems = list.GetItems(camlQuery);
clientContext.Load(listItems);
clientContext.ExecuteQuery();
results = listItems.ToList();
}
Here is the crucial detail (apart from the obvious <Where><Eq><FieldRef Name=\"ContentType\" /><Value Type=\"Computed\">I-Demand</Value></Eq></Where>):
ViewXml = string.Format("<View Scope=\"RecursiveAll\">{0}</View>", viewXml)
In fact, it's Scope=\"RecursiveAll\" that is the important part. I encountered it when looking with Fiddler to the various requests that were sent to the server and noticing that the working calls all included this:
<Property Name="ViewXml" Type="String"><View Scope="RecursiveAll">
<Query>
</Query>
</View></Property>
On a whim I decided to add Scope="RecursiveAll" to my code, and it worked.
I use Nest client to use ElasticSearch .I want to search in ElasticSearch :
SearchRequest countRequest = new SearchRequest
{
//Somthing
};
client.Search<Post>(countRequest);
On other hand :
client.Search<Post>(s=>s.Index("IndexName").Query(...))
How i can set index name by SearchRequest class search ?
This is for those using newer versions of NEST. In 2.0.1, I am unable to find the Indices property in SearchRequest. However, you can pass them in through the constructor:
var request = new SearchRequest<Post>("IndexName", "TypeName");
I map the index and type on the ConnectionSettings like so.
ConnectionSettings settings = new ConnectionSettings("url");
settings.MapDefaultTypeIndices(t => t.Add(typeof(Post), "IndexName"));
settings.MapDefaultTypeNames(t => t.Add(typeof(Post), "TypeName"));
Other ways to tell NEST the index and type:
client.Search<Post>(s => s.Index("IndexName").Type("TypeName").From(0));
or apply the ElasticsearchTypeAttribute on the type.
[ElasticsearchType(Name = "TypeName")]
public class Post{ }
SearchRequest contains an Indices property, so that you can specify multiple indices to search across. In your case, you could just pass the single index like so:
var request = new SearchRequest
{
Indices = new IndexNameMarker[] { "IndexName" }
};
Another option would be to map your Post type to the index it belongs to, and use the typed SearchRequest<T> to let NEST infer the index name.
I was trying to solve a bit different task with ES v5 (json request was pushed from the file) but also had the same problem with setting the indexName. So, my solution was to add index querystring parameter. Using this in integration tests:
public static class ElasticSearchClientHelper
{
public static ISearchResponse<T> SearchByJson<T>(this IElasticClient client, string json, string indexName, Dictionary<string, object> queryStringParams = null) where T : class
{
var qs = new Dictionary<string, object>()
{
{"index", indexName}
};
queryStringParams?.ForEach(pair => qs.Add(pair.Key, pair.Value));
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(json)))
{
var searchRequest = client.Serializer.Deserialize<SearchRequest>(stream);
((IRequestParameters)((IRequest<SearchRequestParameters>)searchRequest).RequestParameters).QueryString = qs;
return client.Search<T>(searchRequest);
}
}
}