Web API with Entity Framework inheritance - entity-framework

Suppose I have the following entities:
abstract class User
{
string Id
string Name
}
class UserA : User
{
List<UserB> Bs
}
class UserB : User
{
string UserAId
[ForeignKey("UserAId"), JsonIgnore]
UserA UserA
}
I want to load all of them in one query and get only the id of the collection. For example, if return
[HttpGet]
public IEnumerable<Usuario> Get()
{
return _context.Users.ToList();
}
The response include all data from "Bs" collection
[
{
"id": "0",
"name": "User A",
"Bs": [
{
"id": "1",
"name" : ....
"aId": ....
},
{
"id": "2",
"name" : ....
"aId": ....
}
]
},
{
"aId": "0",
"id": "1",
"name": "User B 1"
},
{
"aId": "0",
"id": "2",
"name": "User B 2"
}
]
How to get the collection without the extra properties?
[
{
"id": "0",
"name": "User A",
"Bs": [
{
"id": "1"
},
{
"id": "2"
}
]
},
{
"aId": "0",
"id": "1",
"name": "User B 1"
},
{
"aId": "0",
"id": "2",
"name": "User B 2"
}
]
And return this json without "aId" and "name" from the "Bs" collection

I think you can use a select statement to project the id like:
_context.Users.Select(user => user.id)
You will have to change the return type
Reference:
https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/method-based-query-syntax-examples-projection

I resolved this issue with this method:
[HttpGet]
public IEnumerable<dynamic> Get()
{
IEnumerable<dynamic> res = _context.Users.OfType<UserA>()
.Select(u => new {Id = u.Id, Name = u.Name, Users = u.Users.Select(ui => new { Id = ui.Id }) })
.ToArray();
res = res.Concat<dynamic>(_context.Users.OfType<UserB>());
return res;
}

To return the ids from the type UserA's Bs collection, you need to filter out the values based on the type and then use SelectMany on the Bs collection
[HttpGet]
public IEnumerable<int> Get()
{
return _context.Where(e => (e is UserA))
.Select(u => (UserA)u)
.SelectMany(b => b.Bs)
.ToList();
}

Related

Cosmos DB query fail if parent object is null

I am converting Mongodb to Cosmos DB without any code change. I use spring-boot-starter-data-mongo api and org.springframework.data.mongodb.core.query.Query to select only few fields in document not all fields.
Selecting _id,address.primary.email,address.primary.secondary from emp1 it works fine, if I use the same query select emp2, it fails, because emp2 doesn't have secondary address.
How to fix this issue ?
Query: { "_id" : { "$in" : ["Emp2"] } }, Fields: { "_id" :
1,"address.primary.email":1,"address.secondary.email":1},, Sort: { }
mongoTemplate.find(query,EmployeeColl.class);
[
{
"_id": "Emp1",
"name": "Name1",
"address": {
"primary": {
"email": "eamp1#gmail.com"
},
"secondary": {
"email": "emp1sec#gmail.com"
}
}
},
{
"_id": "Emp2",
"name": "Name2",
"address": {
"primary": {
"email": "emp2#gmail.com"
}
}
}
]
Exception:
UncategorizedMongoDbException: Query failed with error code 1 and error message
org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:132)
at org.springframework.data.mongodb.core.MongoTemplate.potentiallyConvertRuntimeException(MongoTemplate.java:2607)
at org.springframework.data.mongodb.core.MongoTemplate.executeFindMultiInternal(MongoTemplate.java:2474)

Mongo find() within specific array

I'm trying to find items with a specific path \ parent.
Example data:
Document A:
{
"traces": [{
"act": {
"account": "555",
"name": "Bob"
}
},
{
"act": {
"account": "666",
"name": "Mary"
}
}
],
"other": [{
"act": {
"account": "555",
"volume": "PPPPP"
}
}
]
}
Document B:
{
"traces": [
{
"act": {
"account": "666",
"name": "Mary"
}
}
],
"other": [{
"act": {
"account": "555",
"volume": "PPPPP"
}
}
]
}
So when searching the above two document, I want my search to match Document A but NOT document B
If I use the below find statement:
db.action_traces.find({ "act.account" : { $in: [ "555" ]}).limit().forEach(function(result){
print(.....);
});
It seems like it will match A and B because both have an elements under the "other" section that matches.
How can I specify that I only want to match traces.{Any Element In Array}.act.account ?

mongodb aggregation lookup using ObjectId

I am struggling with what seems to a basic lookup in mongodb. I can't figure out what is going wrong after trying multiple combinations. I see that there are many questions on SO addressing it, but nothing works after trying all the answers.
Here's my users collection
Here's my items collection
Each item has a single owner which maps to the user's _id in users collection.
For my query, I am trying to fetch items with their corresponding users. This is the query
db.items.aggregate([
{
"$lookup" : {
localField : "owner",
from : "users",
foreignField : "_id",
as : "users"
}
}
])
It returns this -
I have tried different variations - such as
db.items.aggregate([
{
"$lookup" : {
localField : "owner.str",
from : "users",
foreignField : "_id.str",
as : "users"
}
}
])
which results in the array of users getting populated incorrectly (with all users!).
What am I doing wrong?
EDIT
here's the items collection
{
"_id": {
"$oid": "5b268395c176db1548bd92c2"
},
"title": "Item #1",
"description": "Item 1 Description",
"categories": [
{
"$ref": "categories",
"$id": {
"$oid": "5b268248c176db1548bd92af"
}
}
],
"status": "borrowed",
"image": "http://cdn.site.com/testimage.png",
"borrower": "5b2684a0c176db1548bd92d5",
"owner": {
"$ref": "users",
"$id": {
"$oid": "5aecc8012d3d947ba130800d"
}
}
}
{
"_id": {
"$oid": "5b2c2c4d3c70af2da07d1266"
},
"title": "Item 2",
"description": "Item 2 Description",
"categories": [
{
"$ref": "categories",
"$id": {
"$oid": "5b268248c176db1548bd92af"
}
}
],
"status": "Available",
"image": "http://cdn.site.com/testimage1.png",
"borrower": null,
"owner": {
"$ref": "users",
"$id": {
"$oid": "5b2684a0c176db1548bd92d5"
}
}
}
Here's the users collection :
{
"_id": {
"$oid": "5aecc8012d3d947ba130800d"
},
"email": "n.y#gmail.com",
"registeredOn": "20/10/2018 12:12:29 AM",
"avatarURL": "http://gravtar.com/12334",
"friends": []
}
{
"_id": {
"$oid": "5b2684a0c176db1548bd92d5"
},
"email": "j.v#gmail.com",
"registeredOn": "20/10/2018 12:12:29 AM",
"avatarURL": "http://gravtar.com/12334",
"friends": [],
"wishlist": [
{
"$ref": "items",
"$id": {
"$oid": "5b2831543c70af2da07d11da"
}
}
]
}
The localField and foreignField should be of the same data type. Your are DBRef and ObjectId respectively.
If you want to populate a items record with the corresponding user, I think you can use the populate option in mongoose find API
Sample code:
this.read = function(query, populate, onSuccess, onFailure, forcePull, sortQuery, ttl, limitValue, selectQuery) {
var scope = this;
logger.info(this.TAG, "Read operation execution started on ORM Object: "
+ modelName + " with query: " + JSON.stringify(query));
if (query) {
var queryObject = this._model.find(query);
if (populate) {
queryObject = queryObject.populate(populate);
}
if (selectQuery) {
queryObject = queryObject.select(selectQuery);
}
if (sortQuery) {
queryObject = queryObject.sort(sortQuery);
}
if (limitValue) {
queryObject = queryObject.limit(limitValue);
}
queryObject.exec(function(error, records) {
if (error) {
logger.error(scope.TAG, "Error while ORM read: " + JSON.stringify(error));
onFailure(error);
return;
}
logger.info(scope.TAG, "Record read successfully: " + JSON.stringify(records));
onSuccess(records);
});
}
}
You can pass populate as an array of strings like ['owner'] in your case

MongoDB query in java for array fields using ProjectionOperation

Below is the JSON structure for a Store document:
{
{
"_id":"87348378",
"name": "ABC store",
"type": "Books",
"books": [
{
"name": "love",
"id": "1",
"types":{
"type":"love",
"number":"1"
}
},
{
"name": "coreman",
"id": "2",
"types":{
"type":"love",
"number":"1"
}
}
]
},
{
"_id":"87348",
"name": "Some store",
"type": "Books",
"books": [
{
"name": "JAVA",
"id": "1",
"types":{
"type":"Programming",
"number":"2"
}
},
{
"name": "coreman",
"id": "2",
"types":{
"type":"Programming",
"number":"3"
}
}
]
}
}
I need to get the all the stores, which are of a Bookstore type. But, I just want to return certain fields from the Books array(Name & type from types)
Using the following query to get the result:
db.getCollection('store').aggregate([{
"$project" : { "name" : 1 , "type" : 1 ,
"books":{"name":1,"types":{"type":1}}}
},
{ "$group" : { "_id" : "$type",
"books" : { "$push" : "$$ROOT"}}}])
Could anyone help me out to generate the same query with Spring/Java.
Note: I have seen addInclude method has like below in spring docs.
reference: https://docs.spring.io/spring-data/data-mongo/docs/current/api/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.html
**org.springframework.data.mongodb.core.aggregation**
andInclude
public ProjectionOperation andInclude(String... fieldNames)
Includes the given fields into the projection.
Parameters:
fieldNames - must not be null.
Returns:
andInclude
public ProjectionOperation andInclude(Fields fields)
Includes the given fields into the projection.
Parameters:
fields - must not be null.
Returns:

MongoDB find data from array by field name

I have a mongoDB record like the below mentioned-
{
"d": {
"education": [
{
"school": { "name": "one", "id": "1" }
},
{
"school": { "name" : "two", "id" : "2" }
}
]
}
}
now I am running a mongo query to fetch all the school name I have in my record, which is like this-
db.test.find({},{"d.education.0.school.name":"1"})
but the result is not what I am looking for, it is giving empty-
{
"_id": ObjectId("5722385b964f6cb39d49f875"),
"d" : { "education" : [ { }, { } ] }
}
I am hoping to get result something like this-
{
"_id": ObjectId("5087c96338aeb0538a832574"),
"d": {
"education": [
{
"school": { "name" : "one" }
}
]
}
}
The name of the school from first record of the school array. Please help!
Try This:
db.test.aggregate([{"$project":
{"d.education.school.name":true}},
{$unwind:"$d.education.school"},
{"$limit":1}])