I'm trying to implament a search engine and wonder what is the best way to perform a search on collection of entities, while entity is an object of data, and the search criteria is changing from time to time: in the number of fields to search by, and in the which fields to search by. for example:
given a collection of itemEntity, (itemEntity is an object contains id, name, gender, age...ect.) I would like to be flexible with search: you can search by name + gender , or you can search by id only and so on.
How to do it?
p.s.
I'm writing in c#
Scott Gu blogged about the dynamic linq expressions, you can find something useful there.
NEVERMIND
THANKS FOR TRYING TO HELP
DID IT BY MY SELF...
MOVE ON ALL SEARCH CRITERIA,(RECIEVE IT IN A DICTIONARY), THEN BY SWITCH CASE - DOING A LINQ SELECT QUERY -> GOT THE RESULTS.
Related
In kentico the standard way to get documents in below (which I believe is based on ObjectQuery and has linq commands). Im trying to filter it by one more field "newsCategory" which contains data like "1|2|3". So I cant add .Search("newsCategory", 1) etc because I need to split the list before I can search it. What direction should I be looking? A select sub-query? (Im new to linq)
// Get documents
var news = DocumentHelper.GetDocuments("CMS.News")
.OnSite("CorporateSite")
.Path("/News", PathTypeEnum.Children)
.Culture("en-us")
.CombineWithDefaultCulture(false);
As far as this is a field from the coupled table, you can't access it through property, but have to use GetValue() instead. Once you've got, you can work with it like with regular string:
var news = DocumentHelper.GetDocuments("CMS.News")
.OnSite("CorporateSite")
.Path("/News", PathTypeEnum.Children)
.Culture("en-us")
.CombineWithDefaultCulture(false)
.Where(d => d.GetStringValue("newsCategory","").Split('|').Contains("1"));
Are you sure your data is 1|2|3 and not 1|2|3| or |1|2|3 ?
If it is, you could do .Where("NewsCategory", QueryOperator.Like, "%" + id + "|%")
Otherwise you may have to get back more results, and then loop through them and split the values to find the exact one you want.
EDIT: Check out this article that shows some more advanced where commands you can use with the Data Query API. You should be able to MacGyver a proper filter with those options.
I believe you're looking for:
.WhereLike("DocumentCategoryID", "CategoryID");
//OR
.WhereLike("DocumentCategory","CategoryName");
I don't have v8 installed to double check which exact key/value pair to filter by, but according to this Document Query API article you filter document sets with the WhereLike() method.
According to the API documentation, GetDocuments() returns a MultiDocumentQuery object. I'm not 100% certain if that implements IEnumerable, so you may not even be able to use LINQ with it.
I believe something like this would work. There is a wherein property that should be able to pull the value out. Not exactly sure how it would handle the scenario of having a 1 and then an 11, but it may be work looking into.
// Get documents
var news = DocumentHelper.GetDocuments("CMS.News")
.OnSite("CorporateSite")
.Path("/News", PathTypeEnum.Children)
.Culture("en-us")
.CombineWithDefaultCulture(false)
.WhereIn("NewsCategory",1);
I am using the official C# MongoDB driver.
If I have an index on three elements {"firstname":1,"surname":1,"companyname":1} can I search the collection by using a regular expression that directly matches against the index value?
So, if someone enters "sun bat" as a search term, I would create a regex as follows
(?=.\bsun)(?=.\bbat).* and this should match any index entries where firstname or surname or companyname starts with 'sun' AND where firstname or surname or companyname starts with 'bat'.
If I can't do it this way, how can I do it? The user just types their search terms, so I won't know which element (firstname, surname, companyname) each search term (sun or bat) refers to.
Update: for MongoDB 2.4 and above you should not use this method but use MongoDB's text index instead.
Below is the original and still relevant answer for MongoDB < 2.4.
Great question. Keep this in mind:
MongoDB can only use one index per query.
Queries that use regular expressions only use an index when the regex is rooted and case sensitive.
The best way to do a search across multiple fields is to create an array of search terms (lower case) for each document and index that field. This takes advantage of the multi-keys feature of MongoDB.
So the document might look like:
{
"firstname": "Tyler",
"surname": "Brock",
"companyname": "Awesome, Inc.",
"search_terms": [ "tyler", "brock", "awesome inc"]
}
You would create an index: db.users.ensureIndex({ "search_terms": 1 })
Then when someone searches for "Tyler", you smash the case and search the collection using a case sensitive regex that matches the beginning of the string:
db.users.find({ "search_terms": /^tyler/ })
What mongodb does when executing this query is to try and match your term to every element of the array (the index is setup that way too -- so it's speedy). Hopefully that will get you where you need to be, good luck.
Note: These examples are in the shell. I have never written a single line of C# but the concepts will translate even though the syntax may differ.
I want to simply search a database for a certain string, how can i accomplish this using linq and EF (if using these tools for it are not practical I am open to any suggestions). I just want to take a string and search my usernames, the search should be able to handle things only parts of the username (using some sort of 'contains' function)
The basics of what you are asking is..
var found = MyContext.Users.Where(user => user.UserName.Contains(searchString));
You would need to substitute actual entity names/values for the example code posted.
I have a basic datatable, it can be completely generic for this example, except for that it contains a Username column.
I'd like to have a simple textbox and a button that performs a similarity search on the Username field. I know I can use the .Contains() method and it will translate to LIKE in sql, but is this the correct way of doing this?
Secondly, suppose that I have another item in a many to many relationship that I also want to search, in this case Label.
Data
{
ID,
Name,
...
}
Many
{
DataID,
OtherID
}
Other
{
ID,
Label
}
I'd eventually like to find all of the Data items with a Label similar to some search clause. Do I again just use .Contains?
I'd then like to sort to get the best matches for Username and Label in the same query; how can the combined likeness of {Username and Label} be sorted?
Edit: How are a LIKE query's results sorted? It is simply based on the index, and a binary it matches vs it does not match? I guess I'm not that concerned with a similarity score per say, I was more or less just wondering about the mechanism. It seems as though its pretty easy to return LIKE queries, but I've always thought that LIKE was a poor choice because it doesn't use indexes in the db. Is this true, if so does it matter?
String similarity isn't something SQL can do well. Your best bet may be to find all the matches with the same first two (or three if necessary) characters and then, assuming this is a manageable number, compute the similarity score client-side using the Levenshtein distance or similar (see http://en.wikipedia.org/wiki/Levenshtein_distance).
Or if you are feeling brave you could try something like this! http://anastasiosyal.com/archive/2009/01/11/18.aspx
I have been landed into the middle of a project that is using MVC2 & NHibernate. I haven't worked with NHibernate before, so as simple as this question might seem, I'm a bit out of my depth.
I have to create a directory for a number of Company Groups. The first task is to get a distinct list of the first letter for each company.
So if we have
ACompany1
ACompnay2
BCompany1
DCompany1
DCompany2
ECompany1
I need to get a list like
A B D E (note, there's no 'C')
Can somebody please provide me with an outline of what I need to do? Thanks
Assuming the class name is Company and the property is Name...
var groups = session.CreateQuery(
"select distinct substring(Name, 1, 1) from Company")
.List<string>()
I wonder if you are approaching this from the wrong direction. NHibernate is used to map your database objects to your domain objects. You could create some custom map file that use a formula to get you the distinct characters but I think this is one of those cases where a simple SQL query would suffice.
The alternative would be load all the companies into Memory and use linq to get the names.
companies.Select(company => company.Name.Substring(0, 1));
I sometimes get blinkered when using a mocking framework and struggle to mock a particular entity, it isn't till I step back I realise that it would be easier and cleaner to mock my own entity.
First you need to decide how will you do it with sql. Probably you will use some kind of SUBSTRING function. After you solve it, you can write similar HQL query.