UpdateOperations embedded array - arrays

I have an structure like this:
{
_id: 123,
bs: [
{
_id: 234,
cs: [
{
_id: 456,
ds : [
{
_id: 678,
emails[
"email#gmail.com"
]
}
]
}
]
}
]
}
My classes in Morphia seems like this
#Entity
public class A {
#Id
private ObjectId id;
#Embedded
private List<B> bs;
}
public class B {
private ObjectId id;
#Embedded
private List<C> cs;
}
public class C {
private ObjectId id;
#Embedded
private List<D> ds;
}
public class D {
private ObjectId id;
#Embedded
private List<String> emails;
}
What I am trying to do is insert an email inside embedded array with Morphia without retrieve all element A and use updateFirst.
This is the query I am trying execute
Query<Event> query = this.basicDAO.createQuery();
query.criteria(Mapper.ID_KEY).equal(new ObjectId(aID));
query.criteria("bs.cs.id").equal(new ObjectId(cID));
query.criteria("bs.cs.ds.id").equal(dID);
UpdateOperations<Event> updateOps = this.basicDAO.createUpdateOperations().set("bs.cs.ds.$.emails", email);
this.basicDAO.update(query, updateOps);
I also read about this post Update an item in an array that is in an array with said that
$ operator does not work "with queries that traverse nested arrays".
So I tried something like:
D d = new D(dID);
C c = new C(new ObjectId(cID));
Query<Event> query = this.basicDAO.createQuery();
query.criteria(Mapper.ID_KEY).equal(new ObjectId(aID));
query.field("bs.cs").hasThisElement(c);
query.field("bs.cs.ds").hasThisElement(d);
UpdateOperations<Event> updateOps = this.basicDAO.createUpdateOperations().set("bs.cs.ds.emails", email);
this.basicDAO.update(query, updateOps);
However it still doesn't work. Any idea how solve this? The error message that I receive is cannot use the part ... to transverse the element

Based on your stand-in use case, I think you should "invert" your schema. Each document will represent a lecture and will be tagged with its theme, edition, and event:
{
"_id" : ObjectId("54da1ff0a9ce603a239c3075"),
"event" : "X0004",
"edition" : "A0002,
"theme" : "RT0005",
"votes" : 22
}
event, edition, and theme can be some kind of identifiers, and might be references to event, edition, and theme documents in other collections. To cast a vote for a particular lecture, just update it by _id:
db.test.update({ "_id" : ObjectId("54da1ff0a9ce603a239c3075") }, { "$inc" : { "votes" : 1 } })
While I don't know your full requirements, I think this is a better basic design given your example use case.

Related

$http post from angularjs to C# MVC view model, have correct List count but the values are null

I have the following post request using $http
var registration = {
userId: 23,
groupings: [
{ Id: 1, Name: 'Test Group 1', Description: 'Yo' },
{ Id: 4, Name: 'Test Group 4', Description: 'Er' }
]
}
$http({
method: 'POST',
url: url,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
data: $.param({
code: eventCode,
UserId: registration.userId
Groupings: registration.groupings
})
})
And then on my action
[HttpPost]
public ActionResult New(string code, RegistrationVM model)
{
:
:
:
}
public class RegistrationVM
{
public int UserId {get;set;}
public IEnumerable<GroupingVM> Groupings { get; set; }
}
public class GroupingVM{
public int Id {get;set;}
public string Name {get;set;}
public string Description {get;set;}
public int AnotherPropertyId {get;set;}
public ANewClass ANewClass {get;set;}
}
Whenever the post happens, I would have the model properties reflect what I posted except the IEnumerable (Groupings) property. Let's say I post with 2 objects on the Groupings property, when I go to the Action, the Groupings property will have a count of 2 but every instance would have either NULL or 0 values on each object. I'm trying to figure out how I'm messing the post.
First, make the controller take one object as a parameter. Add the "string code" to the RegistrationVM and remove the string code as a parameter.
Then do the same when you create the client object.
Secondly, instead of using the content type "x-www-form-urlencoded" use the "application/json" which is better suited to pass objects.
Before posting the data you need to stringify the obj with data: JSON.stringify(registration)
For more details, read the comments on the question.

LINQ : filter multiple string values - partial match - not full match as in multiple online examples

There are many good examples of searching multiple string values in LINQ e.g.
public static Product[] GetProducts(Guid[] prodIDs)
{
return (from p in GetProducts()
where prodIDs.Contains(p.ProductID)
select p).ToArray<Product>();
}
I have a list of Products that I need to match from a customer,
but I dont have an exact match - the Customers List Of Products contains my ProductID - but it is not exact - e.g.
Customer MyCompany
Description Description
Prod1XY Prod1
AProd2B Prod2
XXXProd3 Prod3
I thus cannot filter from the prodIDs [string array] because Prod1 does not contain Prod1XY
and thus cannot use the examples that are available.
How can I effectively change (reverse) the working examples
as to search CustomerProducts where it contains my Product Description please?
So to confirm : this is not a duplicate. The examples use the string[] x
input parameter and then searches:
where x.contains
I need help to get it : myProducts.Contains(x)
another online example modified to show the situation:
static void Main(string[] args) {
var table = new[] {
new { uid = 1 },
new { uid = 2 },
new { uid = 3 },
new { uid = 4 },
new { uid = 5 }
};
var stringarray = new[] { "1", "5", "10" };
var results = from xx in table
where table.Contains(stringarray)
select xx;
foreach (var result in results) {
Console.WriteLine("Result: " + result.uid.ToString());
}
}
It is not clear enough what you are trying to accomplish, but under assumption that you want to select all products where ProductID contains any value from specified list, it looks like that it:
public static Product[] GetProducts(string[] prodIDs)
{
return (from p in GetProducts()
where prodIDs.Any(id=>p.ProductID.Contains(id))
select p).ToArray<Product>();
}
Try this
public static Product[] GetProducts(string[] prodIDs)
{
return (
from p in GetProducts()
from q in prodIDs
where p.ProductID.IndexOf(q) > -1
select p)
.ToArray<Product>();
}

How to include structured data as a parameter of a HTTP GET request?

I would like to include stuctured data as a parameter to my HTTP GET call and think I have it set up correctly, but my API is not receiving the data as I expected. How do I set up both sides to communicate the structured data?
My angular application is asking a complicated question to the REST API written in Web API 2.
The controller method is defined as:
[RoutePrefix("v1/questions")]
public class VersionsController : ApiController
{
[Route("askComplicated")]
[HttpGet]
[ResponseType(typeof(ComplicatedResponseDto))]
public IHttpActionResult AskComplicatedQuestion(ComplicatedRequestDto complicatedRequest)
{
var responseElements = new List<ComplicatedResponseElementDto>();
foreach (var requestElement in complicatedRequest.Elements)
{
responseElements.Add(new ComplicatedResponseElementDto()
{
Id = requestElement.Id,
answer = "it is unknowable!!!"
});
}
return Ok(new ComplicatedResponseDto() { Elements = responseElements.ToArray()});
}
The DTOs:
public class ComplicatedRequestDto
{
public ComplicatedRequestElementDto[] Elements { get; set; }
}
public class ComplicatedRequestElementDto
{
public int Id { get; set; }
public string Question { get; set; }
}
public class ComplicatedResponseDto
{
public ComplicatedResponseElementDto[] Elements { get; set; }
}
public class ComplicatedResponseElementDto
{
public int Id { get; set; }
public string Answer { get; set; }
}
I broke it down this way because I like a simple request and a simple response. I'm adopting the patterns that worked best for my past WCF work (and understand that might be my problem here).
From the angular side, here is my code:
var request = $http({
method: "get",
url: "http://localhost:65520/v1/questions/askComplicated",
data: {
complicatedRequest : {
elements: [
{ id: 2, question: 'what is the meaning of life?' },
{ id: 3, question: 'why am I here?' },
{ id: 4, question: 'what stock should I pick?' }
]
}
}
});
return request.then(handleSuccess, handleError);
When I call the REST API from my angular application, the WEB API 2 application receives it, but the ComplicatedRequestDto is null. How do I properly send that data so it will go through?
Update your API from Get to Post, because when we want to pass complex object it contains more data and we have restrictions to send maximum characters in URL.
Do below modifications:
[RoutePrefix("v1/questions")]
public class VersionsController : ApiController
{
[Route("askComplicated")]
[HttpPost]
[ResponseType(typeof(ComplicatedResponseDto))]
public IHttpActionResult AskComplicatedQuestion([FromBody]ComplicatedRequestDto complicatedRequest)
{
//write ur code here...
}
}
Update your js code as below:
var request = $http({
method: "post",
url: "http://localhost:65520/v1/questions/askComplicated",
data: {
complicatedRequest : {
elements: [
{ id: 2, question: 'what is the meaning of life?' },
{ id: 3, question: 'why am I here?' },
{ id: 4, question: 'what stock should I pick?' }
]
},
}
});
return request.then(handleSuccess, handleError);
You should add [FromUri] anotation before the method parameter to inform WebAPI that you want to load this parameter from the application Uri, and this is where your data goes when you use GET http action with data parameter.
So your code should look like this
[RoutePrefix("v1/questions")]
public class VersionsController : ApiController
{
[Route("askComplicated")]
[HttpGet]
[ResponseType(typeof(ComplicatedResponseDto))]
public IHttpActionResult AskComplicatedQuestion([FromUri]ComplicatedRequestDto complicatedRequest)
{
var responseElements = new List<ComplicatedResponseElementDto>();
foreach (var requestElement in complicatedRequest.Elements)
{
responseElements.Add(new ComplicatedResponseElementDto()
{
Id = requestElement.Id,
answer = "it is unknowable!!!"
});
}
return Ok(new ComplicatedResponseDto() { Elements = responseElements.ToArray()});
}
You also have to correct the payload to match stucture of your classes.
The corect value should look like this:
{
"Elements": [
{
"Id": 1,
"Question": "sample string 2"
},
{
"Id": 1,
"Question": "sample string 2"
}
]
}
And finally to provide the JavaScript code example it will be like (I only have jQuery, but payload will be the same for Angular):
$.ajax({url:"/v1/questions/askComplicated",data: {
"Elements": [
{
"Id": 2,
"Question": "what is the meaning of life?"
},
{
"Id": 3,
"Question": "why am I here?"
}
]
}})

how to add a complextype object dynamically to an array

We have created an array of complextype(Carrier field) objects. See below metadata
{ shortName : 'Person',
namespace : 'Demo',
autoGeneratedKeyType : breeze.AutoGeneratedKeyType.Identity,
"dataProperties": [
{
"name": "carriers",
"complexTypeName":"Carrier:#Test",
"isScalar":false
}]
}
The Carrier entity is defined as below:
{
"shortName": "Carrier",
"namespace": "Test",
"isComplexType": true,
"dataProperties": [
{
"name": "Testing",
"isScalar":true,
"dataType": "String"
}
]
}
We have the following matching data for the above entities:
{
carriers: [
{
Testing : 'InputBox1'
},
{
Testing : 'InputBox2'
}
]
}
We are trying to dynamically add the complextype object(Carrier) to the above carriers array by using the following approach:
var test = {
"Testing" : "Test"
};
var result = manager.createEntity('Carrier', test);
The above code throws an exception(undefined is not a function) inside breeze.debug.js at line number 12457(see below code)
entity = entityType.createEntity(initialValues);
The exception is thrown since the complextype entity does not have 'createEntity' function in it.
What are we missing here?
Excellent question - Sorry I didn't have a chance to address this earlier.
When adding a complexType object you need to use the createInstance() method instead of the createEntity.
var thisEntityType = manager.metadataStore.getEntityType('Carrier');
var thisEntity = thisEntityType.createInstance(initialValues);
Basically you get the complexType and then create an instance of it using the values you want assigned. Keep in mind the initial values should be a hash object of course. Often I will include a helper function to do this for me like this -
function createComplexType(entityType, constructorProperties) {
var thisEntityType = manager.metadataStore.getEntityType(entityType);
var thisEntity = thisEntityType.createInstance(constructorProperties);
return thisEntity;
}

Json array column order

i have the following json:
{
"Header": {
"MCC": "415",
"FO": "0",
"REGID": "5"
},
"Contacts": [
{
"NAME": "jocelyne",
"MO": "70123456"
},
{
"NAME": "eliane",
"MO": "03123456"
}
] }
and i'm parsing the json string into a datatable using this method:
object classes:
Public Class Data
Public Header As Header
Public Contacts As DataTable
End Class
<System.Runtime.Serialization.DataContract()>
Public Class Header
<System.Runtime.Serialization.DataMember(Name:="MCC")>
Public MCC As Integer
<System.Runtime.Serialization.DataMember(Name:="FO")>
Public FO As Integer
<System.Runtime.Serialization.DataMember(Name:="REGID")>
Public RegId As Integer
End Class
.net functions:
Dim data As New Data
data = JsonConvert.DeserializeObject(Of Data)(json)
mcc = data.Header.MCC
FO = data.Header.FO
regid = data.Header.RegId
contactsDT = data.Contacts
my problem is that the contacts array in the json is being parsed as a datatable in the same order as passed in the json... is there a way to change the order of the columns? what i mean is that if i got in the json let's say mo before name i need to get in the datatable name before mo all the time
is there a way to do that?

Resources