RethinkDB filter on nested objects - json

I need the solution for filter data by nested objects.
So, this is my JSON data:
{
"create_datetime": 1431000977 ,
"creator": {
"company": {
"id": 0 ,
"name": "Some name"
} ,
"manager": {
"id": 0 ,
"name": ""
}
} ,
"finished_datetime": 1431615600 ,
"id": "00949296-cbea-4d4a-a780-7c8d918a7fd6" ,
"participants": [ ],
"status": "created" ,
"tender_categories": [
1285
] ,
"views": [ ]
},
{
"create_datetime": 1431416740 ,
"creator": {
"company": {
"id": 70922233 ,
"name": "Some company name"
} ,
"manager": {
"id": 1003546168 ,
"name": "Some manager name"
}
} ,
"finished_datetime": 1432857600 ,
"id": "28e0936b-84e0-4ffc-9ad1-78a1d34e9033" ,
"participants": {
"788190": {
"creator": {
"company": {
"id": 788190 ,
"name": "Company name"
} ,
"manager": {
"id": 1003546168 ,
"name": "Manager Name"
}
} ,
"dt_applied": 1431416778 ,
"viewed": false
}
} ,
"status": "created" ,
"tender_categories": [1303] ,
"views": [788190]
}
I need select one record from this JSON where we have participants, that not viewed. I wrote a lot of code, but one one work.
r.db('test').table('tenders').filter(function(tender) {
return tender('participants').coerceTo('array').map(function(participant) {
return participant('viewed').eq(false)
});
});
and
r.db('pm').table('b2b_tenders').map(function(tender) {
return tender('participants').filter(function(key) {
return tender(key)('viewed').eq(false)
});
});
and so one. Help pls some one.

Any type of filtering with nested objects is perfectly doable. In your case, it seems you want all documents, where all participants have the property view set to false.
Here's a very long, yet complete and safe way of checking for something like this:
r.db('test').table('tenders')
// Only get all documents with `participants` property
.hasFields('participants')
// Only get documents where the `participants` property is an object
.filter(function (row) {
return row('participants').typeOf().eq('OBJECT')
})
// Only get documents where all participants have a `viewed` property
.filter(function (row) {
return row('participants').coerceTo('array')
.map(function (row) {
return row(1).hasFields('viewed')
})
.distinct()
.eq([true])
})
// Only get documents where all participants have a `viewed` property set to `true`
.filter(function (row) {
return row('participants').coerceTo('array')
.map(function (row) {
return row(1)('viewed').eq(false)
})
.distinct()
.eq([true])
})
You can probably take out or change parts of this query to fit your needs and depending on how much you know about the documents that are coming in. But, this query shows how to deal with nested properties.

Related

Mapping data that contains dots in React

I am trying to map the data in React that is coming from the API but I am having problems mapping the object that contains dots for example this: name.en_US.
What is the proper way to map this object and keeping the data structure that I have?
I am getting the date in this format from the API:
{
"user": "User",
"employeeId": "0000",
"businessCustomer": "customer",
"endCustomer": {
"name": "",
"address": "",
"place": ""
},
"device": {
"shipmentIds": "23",
"name.en_US": "wasi",
"name.fi_FI": " masi"
},
"task": {
"time": "2019-02-10T16:55:46.188Z",
"duration": "00:00:24",
"sum": "75€"
}
},
And then I am trying to map it using the following code.
const {
user,
employeeId,
businessCustomer,
endCustomer,
device,
task
} = task;
const{
endCustomerName,
address,
place
} = endCustomer;
const {
shipmentIds,
names
} = device;
const{
en_US,
fi_FI
} = names;
const {
time,
duration,
summa
} = task;
const data = {
"user": "User",
"employeeId": "0000",
"businessCustomer": "customer",
"endCustomer": {
"name": "",
"address": "",
"place": ""
},
"device": {
"shipmentIds": "23",
"name.en_US": "wasi",
"name.fi_FI": " masi"
},
"task": {
"time": "2019-02-10T16:55:46.188Z",
"duration": "00:00:24",
"sum": "75€"
}
};
const { device } = data;
const {
shipmentIds,
'name.en_US': name_en_US,
'name.fi_FI': name_fi_FI
} = device;
const nameUS = device['name.en_US'];
console.log(name_en_US, nameUS);
Use [ ] notation like, device['name.en_US'] .
You can destructure your propery as #Vishnu mentioned, or you could also destructure it by providing a valid key name
const {
shipmentIds,
'name.en_US': name_en_US,
'name.fi_FI': name_fi_FI
} = device;
And then you could access your variable with name_en_US.

Looping and updating data in React

So quite new to React here (mostly backend and devops engineer). I need to fix a bug as the person usually responsible is not available currently.
One of the REST endpoint is formatting dates incorrectly while sending the data to the backend. The data expected from the endpoint for a PUT is
"items": [
{
"uuid": "abc7aba1-47ad-46d1-a3a5-d26ff55e4cf8",
"item_id": "21626227",
"item_description": "Test",
"item_schedule": {
"uuid": "37f8ca4c-6469-4bfb-822e-acfbc02e502e",
"start_date": "2018-12-04",
"end_date": "2018-12-06",
"interval": 3,
"unit": "days",
"occurrence": 1
"schedule_dates": [
{
"uuid": "d5b73ac5-be77-40c5-b11b-45034f70f81f",
"planned_date": "2018-12-04",
"custom": true
}
]
}
},
{
"uuid": "7abca4f4-1717-4136-aec6-3a37b4971c81",
"item_id": "21626229",
"item_description": "Test 2",
"maintenance_plan": "31001827",
"item_schedule": {
"uuid": "5de45d6e-81e8-4c86-9eb2-31c71089c876",
"start_date": null,
"end_date": null,
"interval": null,
"unit": "",
"occurrence": null,
"schedule_dates": [
{
"uuid": "da7ed2e4-053e-4f1d-80ca-2d6d258e8a08",
"planned_date": "2018-12-13",
"custom": true
}
]
}
}
]
Instead what we get for all the dates, i.e. start_date, end_date and planned_dates is (skipping all the right stuff here..)
"end_date": "2018-12-05T13:00:00.000Z",
"start_date": "2018-12-03T13:00:00.000Z"
"planned_date" : "2018-12-03T13:00:00.000Z"
When creating a new schedule for a new item, the old schedule data is incorrectly formatted.
I have tried to loop over all the items and the relevant schedule and dates and correctly format them , but doesn't seem to work.
Do I need to use map here instead of foreach?
const mapDispatchToProps = (dispatch, props) => ({
save: (value, notes) => dispatch(ItemDetailAction.saveLocal(
props.value.merge(
Map(Object.assign(
{
notes: notes.setIn([0, 'created'], undefined),
uuid: props.value.get('uuid'),
},
props.value.getIn(['item', 'type']) === 'P' && {
items: props.value
.get('items').forEach((item) => {
console.log(item.get('item_schedule'));
const start_date = item.get('item_schedule').get('start_date');
if (start_date !== '') {
const formatted_date = moment(start_date).format('YYYY-MM-DD');
//not updating the date-format below in the same array.
item.get('item_schedule').set('start_date',formatted_date);
item.setIn(['item_schedule', 'start_date'],formatted_date);
// this still prints the wrong date-format
console.log(item.get('item_schedule').get('start_date'));
}
}),
},
)),
),
true,
{
then: () => {
props.onCancel();
dispatch(actions.getItemListTable(FilterMaintenance.asParams(props.filters)));
},
}, )), });

How to optimize JsonResult after solving Self Referencing?

The following image describes my model relationship between User and Room.
There is a Many to Many relationship between them,
and I have resolved the Self Reference issue by JSON.NET
and adding some configurations to the Application_Start function.
It looks like:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
Formatting = Newtonsoft.Json.Formatting.Indented,
ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
};
}
I defined a API like this to return All the users in database as Json.
public ActionResult Index()
{
return Content(JsonConvert.SerializeObject(db.UserSet), "application/json");
}
The point is , when I get a JsonResult , it looks like
(Every "User" has a navigation attribute "Room" )
[
{
"Room": [
{
"User": [
{
"Room": [],
"Id": 3,
"Name": "waterball",
"Account": "pppaass",
"Password": "123"
}
],
"Id": 1,
"Name": "sadafsa"
}
],
"Id": 2,
"Name": "waterball",
"Account": "safasfasd",
"Password": "123"
},
{
"Room": [
{
"User": [
{
"Room": [],
"Id": 2,
"Name": "waterball",
"Account": "safasfasd",
"Password": "123"
}
],
"Id": 1,
"Name": "sadafsa"
}
],
"Id": 3,
"Name": "waterball",
"Account": "pppaass",
"Password": "123"
}, ........
Obviously , the result looks complex ,
How can I get only the Id,Name but NO User attributes of each Room ?
Or what exactly is the common way people handle with this problem?
===========================================================
I have changed my codes to reach my requirement,
but is this actually the common way to resolve this...?
Or does it have some potential problems?
public ActionResult Index()
{
var result = from u in db.UserSet
select new
{
Id = u.Id,
Account = u.Account,
Password = u.Password,
Room = from r in u.Room
select new
{
Id = r.Id,
Name = r.Name
}
};
return Content(JsonConvert.SerializeObject(result), "application/json");
}

MongoDB, NodeJS: updating an embedded document with new members

Using: MongoDB and native nodeJS mongoDB driver.
I'm trying to parse all the data from fb graph api, send it to my API and then save it to my DB.
PUT handling in my server:
//Update user's data
app.put('/api/users/:fbuser_id/:category', function(req, res) {
var body = JSON.stringify(req.body);
var rep = /"data":/;
body = body.replace(rep, '"' + req.params.category + '"' + ':');
req.body = JSON.parse(body);
db.fbusers.update({
id: req.params.fbuser_id
}, {
$set: req.body
}, {
safe: true,
multi: false
},
function(e, result) {
if (e) return next(e)
res.send((result === 1) ? {
msg: 'success'
} : {
msg: 'error'
})
});
});
I'm sending 25 elements at a time, and this code just overrides instead of updating the document.
Data I'm sending to the API:
{
"data": [
{
"category": "App page",
"name": "SoundCloud",
"id": "7919071058",
"created_time": "2013-09-16T18:16:59+0000"
},
{
...and so on
}
]
}
Basically my API changes "data" key from sent json to the category name, f.e.:
PUT to /api/users/000/likes will change the "data" key to "likes":
{
"likes": [
{
"category": "App page",
"name": "SoundCloud",
"id": "7919071058",
"created_time": "2013-09-16T18:16:59+0000"
},
{
...and so on
}
]
}
Then this JSON is put to the db.
Hierarchy in mongodb:
{
"_id": ObjectID("556584c8e908f0042836edce"),
"id": "0000000000000",
"email": "XXXX#gmail.com",
"first_name": "XXXXXXXX",
"gender": "male",
"last_name": "XXXXXXXXXX",
"link": "https://www.facebook.com/app_scoped_user_id/0000000000000/",
"locale": "en_US",
"name": "XXXXXXXXXX XXXXXXXXXX",
"timezone": 3,
"updated_time": "2015-05-26T18:11:59+0000",
"verified": true,
"likes": [
{
"category": "App page",
"name": "SoundCloud",
"id": "7919071058",
"created_time": "2013-09-16T18:16:59+0000"
},
{
"category": "App page",
"name": "SoundCloud",
"id": "7919071058",
"created_time": "2013-09-16T18:16:59+0000"
},
{
....and so on
}
]
}
So the problem is that my api overrides the field (in this case "likes") with newly sent data, instead of appending it to already existing data document.
I am pretty sure that I should be using other parameter than "$put" in the update, however, I have no idea which one and how to pass parameters to it programatically.
Use $push with the $each modifier to append multiple values to the array field.
var newLikes = [
{/* new item here */},
{/* new item here */},
{/* new item here */},
];
db.fbusers.update(
{ _id: req.params.fbuser_id },
{ $push: { likes: { $each: newLikes } } }
);
See also the $addToSet operator, it adds a value to an array unless the value is already present, in which case $addToSet does nothing to that array.

Loading TreeStore with JSON that has different children fields

I am having a JSON data like below.
{
"divisions": [{
"name": "division1",
"id": "div1",
"subdivisions": [{
"name": "Sub1Div1",
"id": "div1sub1",
"schemes": [{
"name": "Scheme1",
"id": "scheme1"
}, {
"name": "Scheme2",
"id": "scheme2"
}]
}, {
"name": "Sub2Div1",
"id": "div1sub2",
"schemes": [{
"name": "Scheme3",
"id": "scheme3"
}]
}
]
}]
}
I want to read this into a TreeStore, but cannot change the subfields ( divisions, subdivisions, schemes ) to be the same (eg, children).
How can achieve I this?
When nested JSON is loaded into a TreeStore, essentially the children nodes are loaded through a recursive calls between TreeStore.fillNode() method and NodeInterface.appendChild().
The actual retrieval of each node's children field is done within TreeStore.onNodeAdded() on this line:
dataRoot = reader.getRoot(data);
The getRoot() of the reader is dynamically created in the reader's buildExtractors() method, which is what you'll need to override in order to deal with varying children fields within nested JSON. Here is how it's done:
Ext.define('MyVariJsonReader', {
extend: 'Ext.data.reader.Json',
alias : 'reader.varijson',
buildExtractors : function()
{
var me = this;
me.callParent(arguments);
me.getRoot = function ( aObj ) {
// Special cases
switch( aObj.name )
{
case 'Bill': return aObj[ 'children' ];
case 'Norman': return aObj[ 'sons' ];
}
// Default root is `people`
return aObj[ 'people' ];
};
}
});
This will be able to interpret such JSON:
{
"people":[
{
"name":"Bill",
"expanded":true,
"children":[
{
"name":"Kate",
"leaf":true
},
{
"name":"John",
"leaf":true
}
]
},
{
"name":"Norman",
"expanded":true,
"sons":[
{
"name":"Mike",
"leaf":true
},
{
"name":"Harry",
"leaf":true
}
]
}
]
}
See this JsFiddle for fully working code.