Nest elasticsearch-nested properties have incorrect mappings - elasticsearch

I have a type that I inserted into my elastic search db with
public class Capture
{
public Guid Id { get; set; }
...
[ElasticProperty(Type = FieldType.Nested)]
public IList<CustomerInformation> CustomerInformations { get; set; }
}
However when I do a
var mapping=client.GetMapping<Capture>(o => o.Index("captures").Type("capture"));
the mapping of the customerinformations property is still object and not nested. Why is this? I have even deleted the index and recreated it and that does not solve anything.

Related

Convert the elastic search response to a list

I am using elastic 7.17.3 and NEST 7.17.3
I have a elastic response which I am trying to put in a list. I have below method. The method is generic and is called from different model classes.
public class Account
{
[JsonProperty(AnalyticsFields.AccessRegions)]
public string[] AccessRegions { get; set; }
[JsonProperty(AnalyticsFields.AccessUsers)]
public string[] AccessUsers { get; set; }
[JsonProperty(AnalyticsFields.AccountId)]
public string AccountId { get; set; }
[JsonProperty(AnalyticsFields.AccountIdAndName)]
public string AccountIdAndName { get; set; }
[JsonProperty(AnalyticsFields.AdvisorId)]
public string AdvisorId { get; set; }
[JsonProperty(AnalyticsFields.AdvisorIdAndName)]
public string AdvisorIdAndName { get; set; }
}
This is how the method converting the elastic response looks like
private void AddSearchResponseHits<T>(ISearchResponse<T> searchResponse, List<T> results) where T : class
{
results.AddRange(searchResponse.Hits.Select(h => h.Source).ToArray());
}
The problem is the field value becomes null even thought the searchresponse have the complete response from elastic. Please help me out. The field values should load in respective properties in the model class.

EF CodeFirst computed field in CF entity class

I have added computed fields(Active and CreditsLeft) directly into my CodeFirst entity class. Is it good idea to add computed field logic inside CF Entity class?
public class User : Entity
{
public User()
{
Id = Helper.GetRandomInt(9);
DateStamp = DateTime.UtcNow;
TimeZone = TimeZoneInfo.Utc.Id;
}
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
[Required]
[MaxLength(50)]
public string Email { get; set; }
[Required]
[MaxLength(50)]
public string Password { get; set; }
[MaxLength(50)]
public string FirstName { get; set; }
[MaxLength(50)]
public string LastName { get; set; }
[Required]
public DateTime DateStamp { get; set; }
public virtual ICollection<Order> Orders { get; set; }
public virtual ICollection<Statistic> Statistics { get; set; }
public virtual ICollection<Notification> Notifications { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public bool Active
{
get
{
return Orders.Any(c => c.Active && (c.TransactionType == TransactionType.Order || c.TransactionType == TransactionType.Subscription));
}
}
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public int CreditsLeft
{
get
{
return Orders.Sum(p => p.Credits != null ? p.Credits.Value : 0);
}
}
}
Is it good idea to add computed field logic inside CF Entity class?
Sure, you can do this, but there are a few things you must take care of.
First, the attribute for a property that is computed by business logic is not [DatabaseGenerated(DatabaseGeneratedOption.Computed)], because this indicates that the value is computed in the database (as in a computed column). You should mark the property by the [NotMapped] attribute. This tells Entity Framework to ignore the property in database mapping.
Second, since both properties use Orders, you must make sure that the orders are loaded or can be lazy loaded when either property is accessed. So you may want to load Users with an Include statement (Include(user => user.Orders)). Or else you must ensure that the context is still alive when Active or CreditsLeft is accessed.
Third, you can't address the properties directly in an EF LINQ query, as in
db.Users.Select(u => u.Active);
because EF will throw an exception that it doesn't know Active. You can address the properties only on materialized user objects in memory.

RavenDB SelectMany not supported

I am trying to find one or more documents in RavenDB based on the values of a child collection.
I have the following classes
public class GoldenDocument
{
public GoldenDocument()
{
LinkedDocuments = new List<LinkedDocument>();
MergeMatchFields = new List<MergeMatchField>();
}
public string Id { get; set; }
public Guid SourceRowId { get; set; }
public List<MergeMatchField> MergeMatchFields { get; set; }
public List<LinkedDocument> LinkedDocuments { get; set; }
}
And the class that is in the collection MergeMatchFields
public class MergeMatchField
{
public string Id { get; set; }
public Guid OriginId { get; set; }
public string Name { get; set; }
public MatchType MatchType { get; set; }
public double MatchPerc { get; set; }
public string Value { get; set; }
}
In a List<MergeFields> mergeFields collection I have values that is not stored in RavenDB yet. Values are compared to values in a RavenDB document for find if it is a possible match by executing the following query:
using (var session = documentStore.OpenSession())
{
var docs = from gd in session.Query<GoldenDocument>()
from mf in gd.MergeMatchFields
from tf in mergeFields
where mf.Name == tf.Name
&& JaroWinklerCalculator.jaroWinkler(mf.Value, tf.Value) > .90d
&& !string.IsNullOrEmpty(mf.Value)
select gd;
}
I understand that ravenDB does not support SelectMany() so how would I go about getting the results from the Document store?
Create an index for this that would output the values you want to query on.
Note that you can't just execute arbitrary code the way you do here: JaroWinklerCalculator.jaroWinkler(mf.Value, tf.Value) > .90d
But you can use fuzzy queries, and they will do the same.

raven query on object type throws exception

document Structure:
class UserAccountInfo
{
public String Id { get; set; }
public AccountType AccountType { get; set; }Servicetax
public String MainAccountMobileNo { get; set; }
public UserStatus Status { get; set; }
public String EmailId { get; set; }
public String DisplayName { get; set; }
**public Object User { get; set; }**
}
object stores instance of any type that is mentioned in Account type. the type that is stored in the object can be found using Accountype for ex; if Accountype is customer then instance stored in the object will be AccountinfoCustomer and so on. So using that I've tried to query but getting the following exception from raven.
var Result = sess.Query<UserAccountInfo>().Where(x => x.AccountType == usertype && ((AccountInfoCustomer)x.User).Customerstatus == CustomerStatus.Pending);
{"Url: \"/indexes/dynamic/UserAccountInfos?query=AccountType%253ADistributor%2520AND%2520User).Customerstatus%253APending&start=0&pageSize=128&aggregation=None\"\r\n\r\nSystem.ArgumentException: The field ')_Customerstatus' is not indexed, cannot query on fields that are not indexed\r\n at Raven.Database.Indexing.Index.IndexQueryOperation.AssertQueryDoesNotContainFieldsThatAreNotIndexes()
This should work. Tested in current stable RavenDB 2.0.2230.
Tests here: https://gist.github.com/4692351
Are you on an older version?

Entity FrameWork 4.1 Exception

This is my code:
public void DeleteFolder(Entities.DocumentFolder folder)
{
DeleteFilesFromServer(folder.Id);
_dbContext.Entry(folder).State = EntityState.Deleted;
_dbContext.SaveChanges();
}
public void DeleteFilesFromServer(int id)
{
var allDocuments = _dbContext.Document.Where(x => x.FolderId == id).ToList();
foreach (var filePath in allDocuments.Select(document => HttpContext.Current.Server.MapPath("~/Documents/") + document.DocumentFileName).Where(System.IO.File.Exists))
{
System.IO.File.Delete(filePath);
}
}
public class DocumentFolder
{
public DocumentFolder()
{
Documents=new List<Document>();
}
public int Id { get; set; }
public string FolderName { get; set; }
public int ParentFolderId { get; set; }
public List<Document> Documents { get; set; }
}
public class Document
{
public int Id { get; set; }
public string DocumentName { get; set; }
public string DocumentFileName { get; set; }
public int FolderId { get; set; }
public virtual DocumentFolder Folder { get; set; }
}
By executing the delete operation I got the following exception:
System.InvalidOperationException: The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.
If I remove the DeleteFilesFromServer(int id) method the deletion working. Can someone help me?
If you want to delete the DocumentFolder, you need to delete the Document objects related to the DocumentFolder because in your model the field Folder is not nullable. This happens only if the dbContext knows that the the Document objects exist, i.e. if you load the documents with the Select method.

Resources