aliasing fields in mongodb projections - c#

In mongo projections, you can either include or exclude fields in the output:
{
IncludetField: 1,
ExcludedField: 0
}
These projections are easy to create in c#, using the ProjectionDefinitionBuilder<> methods Include and Exclude.
MongoDb also allows for aliasing fields:
{
alias: "$IncludedField"
}
but I havnen't found a good way of doing this without falling back to strings:
_collection.Aggregate()
.Match(...)
.Project("{alias: '$IncludedField'}");
This can soon become quite messy. Add a $filter in that projection, and you soon end up with quite a complicated string with no help from the compiler at all.
Have I overlooked something? Or is this just the way it is?

This should work:
_collection.Aggregate()
.Match(...)
.Project(x => new { alias = x.IncludedField });

Related

Return EF Object as normal array in C#

After populating an EF Object (users for instance) with data and return it from WebAPI, i get it in json format as follows:
[
{"username":"lakshman553","email":"abc#xyz.com","phone":1234567},
{"username":"lakshman323","email":"pqr#xyz.com","phone":"122267"},
]
Since i use the webapi completely for internal purposes, i would rather like the data as follows:
[
["lakshman553","abc#xyz.com",1234567],
["lakshman323","pqr#xyz.com",1222267]
]
i can decrease the payload drastically by doing this way when the data is high, which typically is the case.
How to achieve this in C#. Iterating through the users object and assigning it to a sized array of row and column count is one approach i know, but is there a straight method for doing this?
thanks.
You could implement this transformation using LINQ extension methods as follows:
// Project each list item into an array of item property values
var array4all = list.Select
(
item => item.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Select(property => property.GetValue(item))
.ToArray()
).ToArray();
BTW, IMHO I'm concerned about this sentence:
Since i use the webapi completely for internal purposes [...]
I believe you're trying to simplify the problem creating a new problem. In terms of coding, readability and maintainaibility I find that you're making things tougher.
Maybe something like obfuscating property names to a, b, c.... and you might use AutoMapper to map a dynamic DTO to your actual model/DTO with full property names. Something like:
{ "a": "hello world", "b": 20 } => { "text": "hello world", "number": 20 }
Or you can take a look at MsgPack, BSON...
If you gzip your server’s response (which you should), then those repeated property names don’t really matter much. On the other hand, having the properties as properties makes handling the data a lot easier for both the provider and the consumer.
You say you use it only for internal purposes, but you’d still need to build a custom parsing mechanism for this when you consume that data. And to do that, you need to have a consistent way of doing so, so you need additional contracts that define e.g. the order of the properties, and—when parsing into C#—also its types etc.
That’s a lot overhead just to reduce the bandwidth, which as I said above doesn’t really matter much once you gzip the data.
Using Json.NET:
var users = new[]
{
new { username = "lakshman553", email = "abc#xyz.com", phone = "1234567" },
new { username = "lakshman323", email = "pqr#xyz.com", phone = "122267" }
};
JsonConvert.SerializeObject(JArray.FromObject(users).Select(_ => _.Values()));
Output:
[["lakshman553","abc#xyz.com","1234567"],["lakshman323","pqr#xyz.com","122267"]]

How to add completion words dynamically to VS2013 Syntax Extension (MEF)

It's very possible that I just don't understand the problem space, but I'm having trouble figuring out the MEF (Editor Classifier project).
I've created (piecing together the Walkthrough guides from MSDN https://msdn.microsoft.com/en-us/library/ee197665.aspx) a syntax highligher for Informix Stored Procedure language.
One major problem I have is - I want to be able to find all instances of the keyword "DEFINE" and populate the word directly following it into the Statement Completion extension I have (currently it's populated from a defined list of words).
Much like C#'s native support - when you define a variable, it becomes available in the autocompletion dropdown.
I got rid of the in class hardcoding (from the walkthrough) and my completion words are defined like this:
List<Completion> completions = new List<Completion>();
CompletionTags completionTags = new CompletionTags();
foreach (string completionTag in completionTags.completionTags)
{
completions.Add(new Completion(completionTag));
};
My CompletionTags class is pretty simple:
class CompletionTags
{
public List completionTags;
public CompletionTags()
{
this.completionTags = new List<string> {
// SQL keywords
"COUNT",
"FROM",
"HAVING",
};
}
I know WHAT I need to do. I somehow need to hijack the buffer when it changes and find all occurrences of 'DEFINE ([a-zA-Z0-9_]{1,})' and add \1 to the completionTags list.
I have no idea HOW to do this. Any pointers in the right (or any) direction at this point would be greatly appreciated.
Be kind - we've all been out of our depth at some stage (I've been programming in C# now for 3 days)...
Reading this answer will be helpful.
Look at:
XML Editor IntelliSense Features
Schema Cache

MongoDB C# driver query operators in QueryDocument or $not $size alternative

I couldn't quite find something like this, hence the question. I have a page\blarg collection that has an array of Categories. I'd like to be able to pull a list of existing categories and I don't want to do a Map Reduce so I decided I would just pull all of the categories and then filter them for uniqueness client side. I'd like to only pull arrays that are not empty, though, so I devised the following query:
{ Categories : { $not { $size : 0 } } }
However I don't know how to replicate it using the driver. $Not takes a BsonValue and $Size just takes an int, I'm not sure how to put a $Size condition in the $Not query. I figured I could use a QueryDocument or something but i'm not sure how to emulate operators via anonymous objects (or at least I haven't seen any documentation on it).
P.S. I realize I might be able to do an Query.EQ("Categories", BsonArray.Create(new List())) or something but I'm interested in the answer for the principle of it at this point, I can think of another scenario where I might want any arrays in which there is more or less than one entry for instance.
You can express your query in C# as follows:
var query = Query.Not("Categories").Size(0);
You can verify that it is in fact the same query with:
var json = query.ToJson();

Common problem for me in C#, is my solution good, stupid, reasonable? (Advanced Beginner)

Ok, understand that I come from Cold Fusion so I tend to think of things in a CF sort of way, and C# and CF are as different as can be in general approach.
So the problem is: I want to pull a "table" (thats how I think of it) of data from a SQL database via LINQ and then I want to do some computations on it in memory. This "table" contains 6 or 7 values of a couple different types.
Right now, my solution is that I do the LINQ query using a Generic List of a custom Type. So my example is the RelevanceTable. I pull some data out that I want to do some evaluation of the data, which first start with .Contains. It appears that .Contains wants to act on the whole list or nothing. So I can use it if I have List<string>, but if I have List<ReferenceTableEntry> where ReferenceTableEntry is my custom type, I would need to override the IEquatable and tell the compiler what exactly "Equals" means.
While this doesn't seem unreasonable, it does seem like a long way to go for a simple problem so I have this sneaking suspicion that my approach is flawed from the get go.
If I want to use LINQ and .Contains, is overriding the Interface the only way? It seems like if there way just a way to say which field to operate on. Is there another collection type besides LIST that maybe has this ability. I have started using List a lot for this and while I have looked and looked, a see some other but not necessarily superior approaches.
I'm not looking for some fine point of performance or compactness or readability, just wondering if I am using a Phillips head screwdriver in a Hex screw. If my approach is a "decent" one, but not the best of course I'd like to know a better, but just knowing that its in the ballpark would give me little "Yeah! I'm not stupid!" and I would finish at least what I am doing completely before switch to another method.
Hope I explained that well enough. Thanks for you help.
What exactly is it you want to do with the table? It isn't clear. However, the standard LINQ (-to-Objects) methods will be available on any typed collection (including List<T>), allowing any range of Where, First, Any, All, etc.
So: what is you are trying to do? If you had the table, what value(s) do you want?
As a guess (based on the Contains stuff) - do you just want:
bool x= table.Any(x=>x.Foo == foo); // or someObj.Foo
?
There are overloads for some of the methods in the List class that takes a delegate (optionally in the form of a lambda expression), that you can use to specify what field to look for.
For example, to look for the item where the Id property is 42:
ReferenceTableEntry found = theList.Find(r => r.Id == 42);
The found variable will have a reference to the first item that matches, or null if no item matched.
There are also some LINQ extensions that takes a delegate or an expression. This will do the same as the Find method:
ReferenceTableEntry found = theList.FirstOrDefault(r => r.Id == 42);
Ok, so if I'm reading this correctly you want to use the contains method. When using this with collections of objects (such as ReferenceTableEntry) you need to be careful because what you're saying is you're checking to see if the collection contains an object that IS the same as the object you're comparing against.
If you use the .Find() or .FindAll() method you can specify the criteria that you want to match on using an anonymous method.
So for example if you want to find all ReferenceTableEntry records in your list that have an Id greater than 1 you could do something like this
List<ReferenceTableEntry> listToSearch = //populate list here
var matches = listToSearch.FindAll(x => x.Id > 1);
matches will be a list of ReferenceTableEntry records that have an ID greater than 1.
having said all that, it's not completely clear that this is what you're trying to do.
Here is the LINQ query involved that creates the object I am talking about, and the problem line is:
.Where (searchWord => queryTerms.Contains(searchWord.Word))
List<queryTerm> queryTerms = MakeQueryTermList();
public static List<RelevanceTableEntry> CreateRelevanceTable(List<queryTerm> queryTerms)
{
SearchDataContext myContext = new SearchDataContext();
var productRelevance = (from pwords in myContext.SearchWordOccuranceProducts
where (myContext.SearchUniqueWords
.Where (searchWord => queryTerms.Contains(searchWord.Word))
.Select (searchWord => searchWord.Id)).Contains(pwords.WordId)
orderby pwords.WordId
select new {pwords.WordId, pwords.Weight, pwords.Position, pwords.ProductId});
}
This query returns a list of WordId's that match the submitted search string (when it was List and it was just the word, that works fine, because as an answerer mentioned before, they were the same type of objects). My custom type here is queryTerms, a List that contains WordId, ProductId, Position, and Weight. From there I go about calculating the relevance by doing various operations on the created object. Sum "Weight" by product, use position matches to bump up Weights, etc. My point for keeping this separate was that the rules for doing those operations will change, but the basic factors involved will not. I would have even rather it be MORE separate (I'm still learning, I don't want to get fancy) but the rules for local and interpreted LINQ queries seems to trip me up when I do.
Since CF has supported queries of queries forever, that's how I tend to lean. Pull the data you need from the db, then do your operations (which includes queries with Aggregate functions) on the in-memory table.
I hope that makes it more clear.

Dynamic "WHERE" like queries on memory objects

What would be the best approach to allow users to define a WHERE-like constraints on objects which are defined like this:
Collection<object[]> data
Collection<string> columnNames
where object[] is a single row.
I was thinking about dynamically creating a strong-typed wrapper and just using Dynamic LINQ but maybe there is a simpler solution?
DataSet's are not really an option since the collections are rather huge (40,000+ records) and I don't want to create DataTable and populate it every time I run a query.
What kind of queries do you need to run? If it's just equality, that's relatively easy:
public static IEnumerable<object[]> WhereEqual(
this IEnumerable<object[]> source,
Collection<string> columnNames,
string column,
object value)
{
int columnIndex = columnNames.IndexOf(column);
if (columnIndex == -1)
{
throw new ArgumentException();
}
return source.Where(row => Object.Equals(row[columnIndex], value);
}
If you need something more complicated, please give us an example of what you'd like to be able to write.
If I get your point : you'd like to support users writting the where clause externally - I mean users are real users and not developers so you seek solution for the uicontrol, code where condition bridge. I just though this because you mentioned dlinq.
So if I'm correct what you want to do is really :
give the user the ability to use column names
give the ability to describe a bool function (which will serve as where criteria)
compose the query dynamically and run
For this task let me propose : Rules from the System.Workflow.Activities.Rules namespace. For rules there're several designers available not to mention the ones shipped with Visual Studio (for the web that's another question, but there're several ones for that too).I'd start with Rules without workflow then examine examples from msdn. It's a very flexible and customizable engine.
One other thing: LINQ has connection to this problem as a function returning IQueryable can defer query execution, you can previously define a query and in another part of the code one can extend the returned queryable based on the user's condition (which then can be sticked with extension methods).
When just using object, LINQ isn't really going to help you very much... is it worth the pain? And Dynamic LINQ is certainly overkill. What is the expected way of using this? I can think of a few ways of adding basic Where operations.... but I'm not sure how helpful it would be.
How about embedding something like IronPython in your project? We use that to allow users to define their own expressions (filters and otherwise) inside a sandbox.
I'm thinking about something like this:
((col1 = "abc") or (col2 = "xyz")) and (col3 = "123")
Ultimately it would be nice to have support for LIKE operator with % wildcard.
Thank you all guys - I've finally found it. It's called NQuery and it's available from CodePlex. In its documentation there is even an example which contains a binding to my very structure - list of column names + list of object[]. Plus fully functional SQL query engine.
Just perfect.

Categories

Resources