How i can combine type C# filled model and mongo language for create update request?
i try this but get types error:
var update = new ObjectUpdateDefinition<User>(user) & Builders<User>.Update.Inc(f => f.FindCount, 1);
FullCode:
var user = new Model
{
Email = email,
Language = language,
Password = password,
// +17 fields
};
// how i can convert all fields to set? and join with query Inc (like AllFieldToSet)?
var update = user.AllFieldToSet() & Builders<User>.Update.Inc(f => f.FindCount, 1);
Models.FindOneAndUpdate<Model>(
f => f.Email == email,
update,
new FindOneAndUpdateOptions<Model> {IsUpsert = true});
Firstly I would begin to ask why do you update so many fields at once, this can have a significant effect on performance and scalability, especially when your collection has indexes, replication and/or sharding involved. Whenever you have to update an indexed field it needs to update the index as well.
There are multiple solutions:
ReplaceOne:
Inc only increments the value, this can be done manually in the model: FindCount++
Manually build the update operator: Just manually build using the builder they provided
Write your own extension using reflection Personally I like type safety but you can use this extension that I wrote (you will just have to extend it and build in null checks, etc.)
public static class UpdateBuilderExtensions
{
public static UpdateDefinition<TDocument> SetAll<TDocument, TModel>(this UpdateDefinition<TDocument> updateBuilder, TModel value, params string[] excludeProperties)
{
foreach (var property in value.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => excludeProperties?.Contains(x.Name) == false))
updateBuilder = Builders<TDocument>.Update.Combine(updateBuilder.Set(property.Name, property.GetValue(value)));
return updateBuilder;
}
}
Usage of it:
You have to exclude properties that have been set already and you have to exclude the BsondId field (if you do not set it manually)
var update = Builders<User>.Update.Inc(x => x.FindCount, 1).SetAll(model, nameof(model.Id), nameof(model.FindCount));
Models.UpdateOne(x => x.Email== "some-email", update, new UpdateOptions
{
IsUpsert = true
});
I am using following code to index document and test results using NEST in .net core application.
But it is not returning any record.
So either I am doing wrong indexing or I have query problem.
Very new to elastic search. So don't know what is wrong with following code as I am trying to index text of text file and searching it for testing.
private static void Index()
{
var settings = new ConnectionSettings().DefaultIndex("ProjectDocuments");
var client = new ElasticClient(settings);
//First, you need to make the routing required when you are creating your index, like this:
client.CreateIndex("ProjectDocuments", d => d
.Mappings(mapping => mapping
.Map<Document>(map => map
.RoutingField(routing => routing
.Required(true))
.AutoMap())
));
Routing routingFromInt = 1;
Document document = new Document()
{
Id = 1,
Content = "Some Text File Text"
};
IIndexResponse result = client.Index<Document>(document, selector => selector
.Id(1)
.Routing(routingFromInt));
//TODO: Following returns 0. so might be issue with indexing itself.
ISearchResponse<Document> searchResponse = client.Search<Document>(query => query.Query(q => q.MatchAll()).Routing(routingFromInt));
var documents = searchResponse.Documents;
}
Issue was with default index name. Index name with Uppercase is not supported in elastic search.
so "ProjectDocuments" was causing issue. Changed it to "project_documents" and started working.
I am trying to bulk a collection of elements inside an index of ElasticSearch using NEST inside a .NET Core application.
Currently what I have is working, and the elements are saved, but Is not saved where I try to do
My client creation:
protected ElasticClient GetClient()
{
var node = new Uri("http://localhost:9200/");
var settings = new ConnectionSettings(node)
.DefaultIndex("TestIndex")
.PrettyJson(true);
return new ElasticClient(settings);
}
Here is how I create the descriptor for bulk all the data
protected BulkDescriptor GenerateBulkDescriptor<T>(IEnumerable<T> elements, string indexName) where T: class, IIndexable
{
var bulkIndexer = new BulkDescriptor();
foreach (var element in elements)
bulkIndexer.Index<T>(i => i
.Document(element)
.Id(element.Id)
.Index(indexName));
return bulkIndexer;
}
Finally, once I have this, here is how I index the data
var descriptor = GenerateBulkDescriptor(indexedElements, "indexed_elements");
var response = GetClient().Bulk(descriptor);
But, If I see how It's stored in the Elastic index using this, that is what I have:
How can I know if is created under TestIndex index? Because as far as I can see, there is just one index created
Thank you a lot in advance
When defining the index operations on the BulkDescriptor, you are explicitly setting the index to use for each operation
foreach (var element in elements)
bulkIndexer.Index<T>(i => i
.Document(element)
.Id(element.Id)
.Index(indexName));
where indexName is "indexed_elements". This is why all documents are indexed into this index and you do not see any in "TestIndex".
The Bulk API allows multiple operations to be defined, which may include indexing documents into different indices. When the index is specified directly on an operation, that will be the index used. If all index operations on a Bulk API call are to take place against the same index, you can omit the index on each operation and instead, specify the index to use on the Bulk API call directly
var defaultIndex = "default_index";
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var settings = new ConnectionSettings(pool)
.DefaultIndex(defaultIndex);
var client = new ElasticClient(settings);
var people = new []
{
new Person { Id = 1, Name = "Paul" },
new Person { Id = 2, Name = "John" },
new Person { Id = 3, Name = "George" },
new Person { Id = 4, Name = "Ringo" },
};
var bulkResponse = client.Bulk(b => b
.Index("people")
.IndexMany(people)
);
which sends the following request
POST http://localhost:9200/people/_bulk
{"index":{"_id":"1","_type":"person"}}
{"id":1,"name":"Paul"}
{"index":{"_id":"2","_type":"person"}}
{"id":2,"name":"John"}
{"index":{"_id":"3","_type":"person"}}
{"id":3,"name":"George"}
{"index":{"_id":"4","_type":"person"}}
{"id":4,"name":"Ringo"}
Note that the URI is /people/bulk and that each JSON object representing an operation does not contain an "_index".
If you omit the .Index() on Bulk API call, it will use the DefaultIndex configured on ConnectionSettings:
var bulkResponse = client.Bulk(b => b
.IndexMany(people)
);
which yields
POST http://localhost:9200/_bulk
{"index":{"_id":"1","_index":"default_index","_type":"person"}}
{"id":1,"name":"Paul"}
{"index":{"_id":"2","_index":"default_index","_type":"person"}}
{"id":2,"name":"John"}
{"index":{"_id":"3","_index":"default_index","_type":"person"}}
{"id":3,"name":"George"}
{"index":{"_id":"4","_index":"default_index","_type":"person"}}
{"id":4,"name":"Ringo"}
You can also specify a default index to use for a given POCO type on ConnectionSettings with DefaultMappingFor<T>(), where T is your POCO type.
After som tests and attemps, I have found a solution.
First of all, it was a problem with the index configured, once I set it in lower case, the index was working fine indexing data inside.
Then, I had the problem of index data in a specific "path" inside the same index, finalyy I found the Type solution from NEST, taking also advantage of the DefaultMappingFor suggested by Russ in the previous answer.
Client definition:
var node = new Uri(_elasticSearchConfiguration.Node);
var settings = new ConnectionSettings(node)
.DefaultMappingFor<IndexedElement>(m => m
.IndexName(_elasticSearchConfiguration.Index)
.TypeName(nameof(IndexedElement).ToLower()))
.PrettyJson(true)
.DisableDirectStreaming();
var client = new ElasticClient(settings);
Then, the BulkDescriptior creation:
var bulkIndexer = new BulkDescriptor();
foreach (var element in elements)
bulkIndexer.Index<IndexedElement>(i => i
.Document(element)
.Type(nameof(IndexedElement).ToLower()))
.Id(element.Id)
);
And finally, data bulk:
client.Bulk(bulkIndexer);
Now, If I perform a call to the index, I can see this
{
"testindex": {
"aliases": {},
"mappings": {
"indexedelement": {
[...]
}
Thank you Russ for your help and for who have had a look to the post.
UPDATE
Finally, it seems that the unique problem was regarding the default index, that it must be lowercase, so, specify the type with the name of the POCO itself is not neccesary, like #RussCam has truly detected in comments above. After changing thedefault index to lowercase, all the different possibilities worked fine.
Thank you all again
I am trying to get the list of files (file is an entity) which has the selected services (service is another entity). The file can have many services.
I tried the following statement, but it does not give the correct results:
var _serviceTypes = viewModel.SelectedServiceTypes;
// _serviceTypes is an array of integers
var resultsTemp = repository.Files.Where(f => f.Services.Select(s => s.ServiceTypeID).Intersect(_serviceTypes).Any());
What am I missing?
EDIT:
_serviceTypes in an array of integers: {int[2]}
The files can have many services, each of which as one service type id (integer)
For instance, a file has two services in it: ambulance (service type id: 3) and hospitalization (service type id: 5). I want to get all the files which have both the services in it.
Some of the following operations should answer your question:
// requested IDs
var requestedIDs = new List<int>();
// the IDs from one file
var IDsInFile = new List<int>();
if (requestedIDs.Except(IDsInFile).Any())
{
// at least some requested IDs are not in the file
}
else
{
// all requested IDs are in the file
}
if (requestedIDs.Intersect(IDsInFile).Any())
{
// at least some requested IDs are in the file
}
else
{
// not a single requested ID is in the file
}
Since you want every file that contains all of the requested services, the correct query would be
var _serviceTypes = viewModel.SelectedServiceTypes;
// _serviceTypes is an array of integers
var resultsTemp = repository.Files.Where(f => !_serviceTypes.Except(f.Services.Select(s => s.ServiceTypeID)).Any());
You're checking if a single element exists in both lists, which is probably not what you had in mind. Try to check if the intersection is equal to the smaller list (assuming it's _serviceTypes, as that's not evident from your code):
var resultsTemp = repository.Files
.Where(f => f.Services.Select(s => s.ServiceTypeID)
.Intersect(_serviceTypes)
.OrderBy(x => x)
.SequenceEqual(_serviceTypes.OrderBy(x => x));
With selected project name, I had loaded iteration paths. Now I need to get the query names that references the selected iteration path.
Code to load iteration paths passing project name:
private void LoadIterationPaths(string projectName)
{
var tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(_tfs.Uri);
var wiStore = tfs.GetService<WorkItemStore>();
var projCollections = wiStore.Projects;
var detailsOfTheSelectedProject = projCollections.Cast<Project>().Where(project => !String.IsNullOrEmpty(_selectedTeamProject.Name))
.FirstOrDefault(project => project.Name.Contains(_selectedTeamProject.Name));
var iterationPathsList = GetIterationPaths(detailsOfTheSelectedProject);
foreach (var iterationPath in iterationPathsList.Where(iterationPath => iterationPath.Contains(projectName)))
{
cmbIterationPath.Items.Add(iterationPath);
}
cmbIterationPath.Enabled = cmbIterationPath.Items.Count > 0;
}
Now, I need to get the list of Query names that references the selected iteration Path. Thanks.
Note: I am able to get all the query names in a project but that i don't need.
For that I used the below code
foreach (StoredQuery qi in detailsOfTheSelectedProject.StoredQueries)
{
cmbQueries.Items.Add(qi.Name);
}
Your code should looks like this
string selectedIterationPath = ...
foreach (StoredQuery qi in detailsOfTheSelectedProject.StoredQueries) {
if (qi.QueryText.Contains(selectedIterationPath) {
cmbQueries.Items.Add(qi.Name);
}
}
This is what me and Beytan Kurt suggested in the comments.
Instead of a dumb Contains, you should use a Regular Expression to account for false positives and negatives.