Related
How can I update a value in a document based on applying functions to another field (which is in a different embedded document)?
With the sample data below, I want to
get the col field for the farm having id 12
multiply that by 0.025
add the current value of the statistic.crypt field
ensure the value is a double by converting it with $toDouble
store the result back into statistic.crypt
data:
{
"_id": {
"$oid": "6128c238c144326c57444227"
},
"statistic": {
"balance": 112570,
"diamond": 14,
"exp": 862.5,
"lvl": 76,
"mn_exp": 2.5,
"lvl_mn_exp": 15,
"coll_ms": 8047,
"all_exp": 67057.8,
"rating": 0,
"crypt": 0
},
"inventory": {
"farm": [{
"id": 12,
"col": 100,
"currency": "diamond",
"cost": 2,
"date": "2021-09-02 18:58:39"
}, {
"id": 14,
"col": 1,
"currency": "diamond",
"cost": 2,
"date": "2021-09-02 16:57:08"
}],
"items": []
},
...
}
My initial attempt is:
self.collection
.update_many({"inventory.farm.id": 12}, [{
"$set": {
"test": {
'$toDouble': {
"$sum": [
{'$multiply':["$inventory.farm.$[].col", 0.025]},
'$test'
]
}
} }
},])
This does not work as it applies to test rather than statistic.crypt, and I cannot figure out how to modify it to apply to statistic.crypt.
A field can be updated based on another in the following stages:
add a field containing the farm
set statistic.crypt to the result of the mathematical expression (applied to the newly embedded farm)
remove extra fields
In code:
self.collection.update_many({"inventory.farm.id": 12 }, [
{
$addFields: {
hh: {
$filter: {
input: "$inventory.farm",
as: "z",
cond: { $eq: ["$$z.id", 12] },
},
},
},
},
{
$set: {
"statistic.crypt": {
$toDouble: {
$sum: [
{
$multiply: [{ $first: "$hh.col" }, 0.025],
},
"statistic.crypt",
],
},
},
},
},
{
$project: {
id_pr: 1,
id_server: 1,
role: 1,
warns: 1,
id_clan: 1,
statistic: 1,
design: 1,
date: 1,
inventory: 1,
voice: 1,
},
},)
I am getting json response from server as below.
[
[{
"ID": 1,
"Date": "11-09-2015",
"Balance": 1496693.00
}, {
"ID": 2,
"Date": "01-10-2015",
"Balance": 1496693.00
}],
[{
"ID": 1,
"Date": "03-09-2000",
"IntAmount": "003.00"
}],
[{
"EmployeeId": "000",
"DesignationName": "deg"
}],
[{
"LoanAmount": "00000.00",
"IntRate": "3.00",
"LoanNo": "56656"
}]
]
I can parse json array with name but in above json there are three arrays without name.
How to parse above json in three different arrays?
If you are positive that the data will always come in the stated format, then you can iterate through the result. See below for example:
main(List<String> args) {
// Define the array of data "object" like this
List<List<Map<String, dynamic>>> arrayOfData = [
[
{"ID": 1, "Date": "11-09-2015", "Balance": 1496693.00},
{"ID": 2, "Date": "01-10-2015", "Balance": 1496693.00}
],
[
{"ID": 1, "Date": "03-09-2000", "IntAmount": "003.00"}
],
[
{"EmployeeId": "000", "DesignationName": "deg"}
],
[
{"LoanAmount": "00000.00", "IntRate": "3.00", "LoanNo": "56656"}
]
];
/*
Iterate through the array of "objects" using forEach,
then, iterate through each resulting array using forEach
*/
arrayOfData.forEach((datasetArray) => datasetArray.forEach((dataset) => print(dataset)));
/*
============== RESULT ========
{ID: 1, Date: 11-09-2015, Balance: 1496693.0}
{ID: 2, Date: 01-10-2015, Balance: 1496693.0}
{ID: 1, Date: 03-09-2000, IntAmount: 003.00}
{EmployeeId: 000, DesignationName: deg}
{LoanAmount: 00000.00, IntRate: 3.00, LoanNo: 56656}
*/
}
I am working on a food delivery app, which uses parse as its backend. I am facing a problem while calling the placeOrder API through
PFCloud.callFunction(inBackground: PlaceOrder, withParameters: params) { (data, err) in}
Please have a look at the JSON which I need to post below.
{
"source": "card_1EVYuOEynlyM6L4SHgBMJYRQ",
"userId": "YjSZYSXEp7",
"data": {
"menuItems": [{
"id": "QSYa2JDcIm",
"title": "Rice With Tibss(Beef)",
"menuTitle": "Rice With Tibss",
"submenuItem": [{
"id": "zaOo6G4KSV",
"name": "Beef",
"price": 12,
"desc": "Fillings?"
}],
"price": 24,
"qty": 1,
"storeId": "yqBCDmzaDP",
"storeName": "Ibex Ethiopian Cusine and Bar",
"orderType": "takeout",
"taxState": 0.0925,
"storeInfo": {
"cart_storeId": "yqBCDmzaDP",
"cart_storeName": "Ibex Ethiopian Cusine and Bar",
"cart_storeImage": "https://res.cloudinary.com/http-get-tolofood-com/image/upload/c_scale,h_199,q_auto,w_270/v1461575640/Ibex_lopx38.jpg",
"cart_storeCuisine": "Ethiopian",
"cart_storeDescription": "We always serve a quality food. We always serve a quality food. We always serve a quality food. We always serve a quality food.",
"cart_storeRating": 3.33,
"cart_storeDelivery": false,
"takeout": true,
"address": "12255 Greenville Ave,Dallas, TX 75243",
"slugname": "TX_DAL_ibex_ethiopian_cuisine_and_bar",
"multiple_location": false,
"cart_storeDeliveryFee": 15,
"cart_storeServes": "Lunch,Dinner",
"busy": false,
"cart_storeSeoSlug": "ibex-ethiopian-cusine-and-bar"
},
"enable": true,
"voice_read_mi_label": "fbgcb",
"voice_read_mi_option": false,
"menuTypeName": "Standard"
}],
"lastOrderType": "takeout",
"searchedAddress": "takeout",
"timeData": {
"day": "06-05-2019",
"time": "12:55 am",
"tz": "America/Los_Angeles"
}
},
"unavailable_option": "restaurant_recommendation"
}
And below is the Swift code which I have used to make pass it.
let storeInfo: Dictionary = [CartStoreId: self.cartStoreId, CartStoreName: self.cartRestaurantName, CartStoreImage: self.cartStoreImage, CartStoreCuisine: self.cartStoreCuisine, CartStoreDescription: self.cartStoreDescription, CartStoreRating: self.cartStoreRating, CartStoreDelivery: self.cartStoreDelivery, Takeout: self.takeOut, Address: self.address, Slugname: self.slugName, MultipleLocation: self.multipleLocation, CartStoreDeliveryFee: self.cartStoreDelivery, CartStoreServes: self.cartStoreServes, Busy: self.busy, CartStoreSeoSlug: self.cartStoreSeoSlug] as Dictionary
let subMenuItem = ["id": "zaOo6G4KSV", "name": "Beef", "price": 12, "desc": "Fillings?", "voice_read_submi_label":"bf", "voice_read_submi_option":false, "disabled": false] as [String: Any]
let ordersDictionary = [
"id" : "1234",
"title" : "Test",
"menuTitle" : "MenuName",
"price" : 23,
"qty" : 2,
"storeId" : 23,
"orderType" : "standard",
"taxState" : 0.22,
"enable" : true,
"menuTypeName" : "Type Name",
"voice_read_mi_label":"fdfs",
"voice_read_mi_option":"false",
"submenuitem": subMenuItem,
"storeInfo": storeInfo
] as Dictionary
let timeData = ["day" : 17-06-2019, "time": "11:00 AM", "tz": "America/Los_Angeles"] as Dictionary
let data = ["menuItems": ordersDictionary, "lastOrderType": "takeout", "searchedAddress": "takeout", "timeData" : timeData] as Dictionary
let params = [UserId: self.userId, "source":"card_1EVYuOEynlyM6L4SHgBMJYRQ", "data": data, "unavailable_option":"restaurant_recommendation","_ApplicationId":"6EuadToYoFGJhI1sX8XnuFBz9tp9l3yH6HxzzXZO", "_JavaScriptKey":"rQkALu9saFtF2oq9yCibyw6mEcs3PVqct3uuP6vg", "_ClientVersion":"js1.6.14", "_InstallationId":"444ec64d-5fcc-7b8e-596e-6be627892c2a",
"_SessionToken":"r:c966376120c8eca77aa63c29d5bebe1a"] as Dictionary
After all this is done I call the parse function like below.
PFCloud.callFunction(inBackground: PlaceOrder, withParameters: params) { (data, err) in
if err != nil {
print(err!)
} else {
print(data!)
}
}
But this gives me error after a few seconds saying
"Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}"
I have searched the web with the error and made fixes accordingly but still no success. Please help me guys.
I noticed that your params var is not compatible with the JSON you sent, there are more fields and also missing fields. Moreover, menuItems and submenuItem are an Array in your JSON and an Object in your code. It is probably making the cloud code function to fail and you are therefore not receiving back a valid JSON. Try the following and check if it works. In the case it works, just replace the values by your vars.
let params = [
"source": "card_1EVYuOEynlyM6L4SHgBMJYRQ",
"userId": "YjSZYSXEp7",
"data": [
"menuItems": [[
"id": "QSYa2JDcIm",
"title": "Rice With Tibss(Beef)",
"menuTitle": "Rice With Tibss",
"submenuItem": [[
"id": "zaOo6G4KSV",
"name": "Beef",
"price": 12,
"desc": "Fillings?"
]],
"price": 24,
"qty": 1,
"storeId": "yqBCDmzaDP",
"storeName": "Ibex Ethiopian Cusine and Bar",
"orderType": "takeout",
"taxState": 0.0925,
"storeInfo": [
"cart_storeId": "yqBCDmzaDP",
"cart_storeName": "Ibex Ethiopian Cusine and Bar",
"cart_storeImage": "https://res.cloudinary.com/http-get-tolofood-com/image/upload/c_scale,h_199,q_auto,w_270/v1461575640/Ibex_lopx38.jpg",
"cart_storeCuisine": "Ethiopian",
"cart_storeDescription": "We always serve a quality food. We always serve a quality food. We always serve a quality food. We always serve a quality food.",
"cart_storeRating": 3.33,
"cart_storeDelivery": false,
"takeout": true,
"address": "12255 Greenville Ave,Dallas, TX 75243",
"slugname": "TX_DAL_ibex_ethiopian_cuisine_and_bar",
"multiple_location": false,
"cart_storeDeliveryFee": 15,
"cart_storeServes": "Lunch,Dinner",
"busy": false,
"cart_storeSeoSlug": "ibex-ethiopian-cusine-and-bar"
],
"enable": true,
"voice_read_mi_label": "fbgcb",
"voice_read_mi_option": false,
"menuTypeName": "Standard"
]],
"lastOrderType": "takeout",
"searchedAddress": "takeout",
"timeData": [
"day": "06-05-2019",
"time": "12:55 am",
"tz": "America/Los_Angeles"
]
],
"unavailable_option": "restaurant_recommendation"
]
I've defined my column metadata for griddle-react like so:
const cols = [
{"columnName": 'id', "displayName": "ID", "visible": false, "order": 1},
{"columnName": 'name', "displayName": "Name", "order": 2, "customComponent": BrandNameLink},
{"columnName": 'description', "displayName": "Description", "order": 3},
{"columnName": 'dateCreated', "displayName": "Date Created", "visible": true, "order": 4, "customComponent": DateComponent},
{"columnName": 'lastUpdated', "displayName": "Last Updated", "visible": true, "order": 5, "customComponent": DateComponent},
];
for the name, dateCreated and lastUpdated I want to pass in additional props to these custom components. For example, my DateComponent looks like so:
import React from 'react';
import Time from 'react-time';
const DateComponent = (props) => {
return (<Time value={props.rowData.dateCreated} format="MM-DD-YYYY" />);
}
export default DateComponent;
But I would like to be able to tell it to use dateCreated or lastUpdated from the rowData vs making 2 nearly identical components (1 for each date property).
Figured this out from this questions.
When you pass a customComponent, you can also pass customComponentMetadata like so:
{"columnName": 'dateCreated', "displayName": "Date Created", "visible": true, "order": 4, "customComponent": DateComponent, customComponentMetadata: {
"dateField": "dateCreated"
}}
And then access it like so:
props.metadata.customComponentMetadata.dateField
That said, the columnName is already passed in as metadata anyway. So while I didn't need to pass custom data for this scenario, I did need it for something else.
The following data is being used to load and display a grid dynamically. The only difference between the two grids is that the first reader takes in the data below as is, but the second grid only knows about the data and the metaData will be generated on the fly. I placed stubs for the fields and columns as this is not the issue and I haven't decided on how I will generate the data yet.
Both of the readers eventually pass the data below to the JsonReader's readRecords()' function via this.callParent([data]);, but the second one does not display the data. The data is there, but I am not sure why it does not display?
There are two links to demos below. The first is a JSFiddle that loads from memory and the second is a Sencha Fiddle that loads through AJAX.
Snippet
var rawFields = [
{ "name": "year", "type": "int" },
{ "name": "standard", "type": "string" },
{ "name": "bitRate", "type": "float" }
];
var rawColumns = [
{ "text" : "Year", "dataIndex" : "year", "flex" : 1 },
{ "text" : "Standard", "dataIndex" : "standard", "flex" : 1 },
{ "text" : "Bit/Sec", "dataIndex" : "bitRate", "flex" : 1 }
];
Ext.define('Example.reader.DynamicReader', {
extend : 'Ext.data.reader.Json',
alias : 'reader.dynamicReader',
readRecords : function(data) {
var response = {
data: data,
metaData : this.createMetaData(data),
success: true
};
console.log(response);
return this.callParent([response]);
},
createMetaData : function(data) {
return {
idProperty : "id",
fields : rawFields, // These will eventually be generated...
columns : rawColumns // These will eventually be generated...
};
}
});
Data
{
"data": [
{
"id": 0,
"year": 1997,
"standard": "802.11",
"bitRate": 2000000
},
{
"id": 1,
"year": 1999,
"standard": "802.11b",
"bitRate": 11000000
},
{
"id": 2,
"year": 1999,
"standard": "802.11a",
"bitRate": 54000000
},
{
"id": 3,
"year": 2003,
"standard": "802.11g",
"bitRate": 54000000
},
{
"id": 4,
"year": 2007,
"standard": "802.11n",
"bitRate": 600000000
},
{
"id": 5,
"year": 2012,
"standard": "802.11ac",
"bitRate": 1000000000
}
],
"metaData": {
"idProperty": "id",
"fields": [
{
"name": "year",
"type": "int"
},
{
"name": "standard",
"type": "string"
},
{
"name": "bitRate",
"type": "float"
}
],
"columns": [
{
"text": "Year",
"dataIndex": "year",
"flex": 1
},
{
"text": "Standard",
"dataIndex": "standard",
"flex": 1
},
{
"text": "Bit/Sec",
"dataIndex": "bitRate",
"flex": 1
}
],
"success": true
}
}
Demos
The following examples both achieve the same thing, so the only difference is the loading of the data.
Loading from Memory
http://jsfiddle.net/MrPolywhirl/zy4z5z8a/
Loading from AJAX
https://fiddle.sencha.com/#fiddle/d3l
I figured out the answer. I needed to specify a root value for the reader so that the data can be mapped properly.
Ext.onReady(function() {
Ext.widget("dynamicGrid", {
title: 'WiFi LAN Data Rates [Dynamic]',
renderTo: Ext.get('example-grid-dynamic'),
readerType: 'dynamicReader',
// This need to match the 'data' key specified in the `response` object
// that was created in readRecords().
readerRoot: 'data',
data : rawData
});
});
The documentation for root notes that the root property has to map to the data portion of the response.
Documentation for Json.root:
Ext.data.reader.Json.root
root : String
The name of the property which contains the data items corresponding to the Model(s) for which this Reader is configured. For JSON reader it's a property name (or a dot-separated list of property names if the root is nested). For XML reader it's a CSS selector. For Array reader the root is not applicable since the data is assumed to be a single-level array of arrays.