Flatten list of dynamic objects in c# - linq

I have a list of dynamics:
var list = new List<dynamic> { Json.Decode(#"{""no"":""001"",""photos"":[""01.jpg"",""02.jpg""]}"), Json.Decode(#"{""no"":""002"",""photos"":[""01.jpg""]}") };
How can i use selectMany to fatten the photos property into:
{"no": "001", "photo": "01.jpg"}
{"no": "001", "photo": "02.jpg"}
{"no": "002", "photo": "01.jpg"}

Believe you want to get flatten list of photos
var photos = list.SelectMany(x=>(DynamicJsonArray)x.photos).Cast<string>();
Output

Related

How to iterate through object keys / obtain keys of object

I am trying to create a dialog that displays a object in a dynamic manner in an adaptive card. Dynamic as in I don't know what the object keys are, how many keys there are, etc.
Assuming that the object will not have nested arrays or other objects (basically the object will look like a map), how can I extract all the keys and put them in an array?
An example of an object that I wish to extract the keys from :
{
"symbol": "MSFT",
"companyName": "Microsoft Corporation",
"primaryExchange": "Nasdaq Global Select",
"sector": "Technology",
"calculationPrice": "close",
"open": 127.42,
"openTime": 1556890200,
"close": 128.9,
"closeTime": 1556913600,
"high": 129.43,
"low": 127.25,
"latestPrice": 128.9,
"latestSource": "Close",
"latestTime": "May 3, 2019",
"latestUpdate": 1556913600,
"latestVolume": 24835154,
"iexRealtimePrice": null,
"iexRealtimeSize": null,
"iexLastUpdated": null,
"delayedPrice": 128.9,
"delayedPriceTime": 1556913600,
"extendedPrice": 129.04,
"extendedChange": 0.14,
"extendedChangePercent": 0.00109,
"extendedPriceTime": 1556917190,
"previousClose": 126.21,
"change": 2.69,
"changePercent": 0.02131,
"iexMarketPercent": null,
"iexVolume": null,
"avgTotalVolume": 22183270,
"iexBidPrice": null,
"iexBidSize": null,
"iexAskPrice": null,
"iexAskSize": null,
"marketCap": 987737229888,
"peRatio": 30.84,
"week52High": 131.37,
"week52Low": 93.96,
"ytdChange": 0.30147812013916003
}
Use the select prebuilt function from Adaptive Expressions.
It would be something like:
select(myobject, x, x.key) and assigning that to a new property (or however you need to use that array).
You can test this out further by using the expressions playground:
https://playgroundclient.azurewebsites.net/
I ran a quick test with the expression:
select(myobject, x, x.key)
And my data/properties as:
{
"myobject": {
"symbol": "MSFT",
"companyName": "Microsoft Corporation",
"primaryExchange": "Nasdaq Global Select",
"sector": "Technology",
"calculationPrice": "close"
}
}
And I get the result:
["symbol","companyName","primaryExchange","sector","calculationPrice"]
Please let me know if I misunderstood your requirement/question. And if this answers your question; please mark as answered.
This can be done use Keys method.
const myObject = {
"symbol": "MSFT",
"companyName": "Microsoft Corporation",
"primaryExchange": "Nasdaq Global Select",
"sector": "Technology",
}
const keys = Object.keys(myObject);
keys.map(key=>console.log(key,"->", myObject[key]));
Now if you have inner object you need to make a function that will check is it object or not. If it's object then you can run the keys method again and push it to a new array.

Merge Model and its Relationship with result like join query in laravel

I'm new at Laravel and Programming at that. I have a problem joining model with its relationship, here is what my model:
class MainClass extends Model
{
public function first()
{
return $this->hasMany(First::class);
}
public function second()
{
return $this->hasMany(Second::class);
}
public function third()
{
return $this->hasMany(Third::class);
}
}
When i try to get MainClass records then load it's relationship like:
$main = Main::where('status', 'ready')->get()
$main->load(['first','second'])
Here's what i got:
[{
"id":"1",
"name":"First Person",
"status": "ready",
"first":[
{"main_id": "1", "prop":"One"},
{"main_id":"1", "prop":"Two"}],
"second":[
{"main_id": "1", "other":"Yes"},
{"main_id":"1", "other":"Two"},
{"main_id":"1", "other":"Three"}]
},{
"id":"5",
"name":"Fifth Person",
"status": "ready",
"first":[
{"main_id": "5", "prop":"Five"},
{"main_id":"5", "prop":"Six"}],
"second":[
{"main_id": "5", "other":"Laptop"},
{"main_id":"5", "other":"Pc"}]
}]
How can i merge that relationship so the result will be like join query,
this is what i want:
[{
"id":"1",
"name":"First Person",
"status": "ready",
"prop":"One",
"other:"Yes"
},{
"id":"1",
"name":"First Person",
"status": "ready",
"prop":"Two",
"other":"Two"
}]
I know there is a way to combine collection with merge or push in laravel, but i can't seem to get it right.
As of why not using join query, because i want to load relationship dynamically, so relation is not always loaded, but sometime they do. While join query, i have to write it manually (as far as i know) :-)
Maybe someone can point me somewhere, or maybe there is a package for something like this?
Thanks in advance
Use eager loading, fetching the collection, then run groupBy, then the each, then the map function to return the results formatted as your wish.
Why not just simply run the joins
You can do it with join;
$main = Main::query()->select(['main.id', 'main.name', 'main.status', 'f.prop', 's.other', 't.blabla'])
->leftJoin('first as f', 'f.main_id', 'main.id')
->leftJoin('second as s', 's.main_id', 'main.id')
->leftJoin('third as t', 't.main_id', 'main.id')
->where('main.status', 'ready')
->get();

Getting undefined when I drill into my redux store

I'm using useSelector to retrieve my store. However when I console.log(items) there is data but when I do this console.log(items.totalAmount) I get undefined.
import {useSelector} from 'react-redux';
const items = useSelector(state => state.items);
//I'm able to see the data
console.log(items)
The data when its logged
[{"code": "SR71", "description": "Keyboard", "quantity": 1, "selling_price": 166.99, "totalAmount": 166.99}, {"code": "10", "description": "Cement", "quantity": 7, "selling_price": 20, "totalAmount": 140}]
//I get undefined
console.log(items.totalAmount);
Could any please explain what am I doing wrong.
items looks like this when you do console.log:
[
{..., "totalAmount": 166.99},
{..., "totalAmount": 140},
...
]
So you can access totalAmount of each items like: items[0].totalAmount
And for getting the totalAmount of all items, you can use:
let sum = Array.from(items).reduce((acc, cur) => acc + cur.totalAmount, 0)
Also i used Array.from since there is no guaranty for items to be a serializable (normal) array. (as you confirmed that it was non-serializable .)

Create or append to an array in a rethinkdb document

How should we append an item to an array if the array exists, or create an array and insert to it.
I tried the merge command but that doesn't allow merging arrays, only replacing them.
r.db('testdb').table('users').get('27e55a4a-a6f8-4ec9-bd02-f55f206700ff').merge({ 'hobbies':['Reading'] })
I further tried passing a function but doesnt seem to work:
r.db('testdb').table('users').get('27e55a4a-a6f8-4ec9-bd02-f55f206700ff').merge(function(user) {
return r.branch(user('hobbies').eq(null),
{ 'hobbies' : ['Reading'] }
user('hobbies').append('Reading'))
});
Consider the below doc structure:
{
"email": email.123#gmail.com, »
"id": "27e55a4a-a6f8-4ec9-bd02-f55f206700ff" ,
"image": https://lh4.googleusercontent.com/-O4ZXcLRpkHE/AAArAAAAAAAI/AdAAAAAAALMM/Fq968TTkd88Y/photo.jpg?sz=50, »
"name": "John Doe"
}
If I would like to add hobbies as an array how should I do it. The query has to work both if the hobby array exists or not.
The most idiomatic way would be .update(function(user) { return {hobbies: user('hobbies').default([]).append('reading')}; })
Finally I have figured out myself.
r.db('testdb').table('users')
.get("27e55a4a-a6f8-4ec9-bd02-f55f206700ff")
.update(function(user){
return r.branch(user.hasFields('hobbies'),
{ hobbies: user('hobbies').append('reading')},
{ hobbies : ['reading']}
)})

Using a Regex against a simple list with `ElemMatch` in MongoDB .NET

Given a document with a list of strings, how would you assemble a C# MongoDB query to regex against each list item?
For example, here's some data.
{
"_id": {
"$oid": "4ded270ab29e220de8935c7b"
},
// ... some other stuff ...
"categories": [
{
"Some Category",
"Another Category",
"Yet Another Category",
"One Last Category"
}
]
},
Ultimately, how would I structure a query like this that could be strongly-typed through the MonoDB LINQ provider?
{ "categories": { $elemMatch: { $regex: someSearch, $options: "i" } } }
I'm trying to make this work with ElemMatch, but I can't seem to structure a BsonRegularExpression to work with that method. If the data was a list of keyed elements, it looks like I could make this work for some key, say itemName.
// Doesn't translate to a list of raw strings.
Query.ElemMatch ("categories", Query.Match("itemName", new BsonRegularExpression (new Regex (someSearch, RegexOptions.IgnoreCase)));
As soon as I try to make that regex work directly on ElemMatch, though, I can't match the overloads.
// Doesn't compile: cannot convert BsonRegularExpress to IMongoQuery.
Query.ElemMatch ("categories", new BsonRegularExpression (new Regex (someSearch, RegexOptions.IgnoreCase)));
Is there some method for converting a BsonRegularExpression into an IMongoQuery object directly?
Or is there some Matches syntax for applying the current iterated element in a list that would allow for a hybrid of the two? Something like this made up code.
// Doesn't work: totally making this up.
Query.ElemMatch ("categories", Query.Matches (iteratorElement, new BsonRegularExpression (new Regex (someSearch, RegexOptions.IgnoreCase)));
I was hoping to avoid just sending a raw string into the MongoDB driver, both so I can escape the search string from injection and so the code isn't littered with magic string field names (instead limited to just the BsonElement attribute on the DB model fields).
This might not be 100% what you are after (as it's not IQueryable); but it does achieve what you want (strongly typed regex filtering of a collection, using Linq):
var videosMongo = DbManager.Db.GetCollection<Video> ("videos");
var videosCollection = videosMongo.AsQueryable<Video> ();
videosMongo.Insert (new Video () {
Id = new ObjectId (),
Tags = new string[]{ "one", "two", "test three", "four test", "five" },
Name = "video one"
});
videosMongo.Insert (new Video () {
Id = new ObjectId (),
Tags = new string[]{ "one", "two", "test three", "four test", "five" },
Name = "video two"
});
videosMongo.Insert (new Video () {
Id = new ObjectId (),
Tags = new string[]{ "one", "two" },
Name = "video three"
});
videosMongo.Insert (new Video () {
Id = new ObjectId (),
Tags = new string[]{ "a test" },
Name = "video four"
});
var videos = videosCollection.Where (v => v.Name == "video four").ToList ();
var collection = DbManager.Db.GetCollection<Video> ("videos");
var regex = new BsonRegularExpression ("test");
var query = Query<Video>.Matches (p => p.Tags, regex);
var results = collection.Find (query).ToList ();
I worked this out by using the excellent resource here : http://www.layerworks.com/blog/2014/11/11/mongodb-shell-csharp-driver-comparison-cheat-cheet

Resources