RavenDB - building dynamic queries - asp.net

I am building a simple CMS with .NET MVC and RavenDB and i need to filter pages with x amount of incoming parameters.
Example Page:
public class Page{
string Name
string Content
List<string> Tags
//etc...
}
In my pages controller i have this method and i want to get all the pages that have matching tags. they must be excluding filter so it is an AND condition that should be added
public ActionResult Index(List<string> tagFilters)
{
var pages = MyRavenSession.Query<Page>().Where( how to compare tagFilters List to pages Tags List? )
return View(pages);
}
I have been searching the internet for answers on this scenario and there should be others that have the same problem.
How should i solve this?
I read that predicatebuilder could not be translated to RavenDB LINQ queries.
I also read that you could build some kind of RavenDB lucene query but i cannot find any examples.

You can do that by using Session.Advanced.LuceneQuery() it allows fine grained dynamic query building

Related

How to send list as parameter for search in angular service to .net core

Please Help me I need to retrieve a list of details using a list of parameters. How to achieve that from angular 10 and .net Core?
Also, Single Entries is working for search. But If I try to enter a second entry in the input field and tried to search it is not working.
The method name is GetPodForwardings.
This is the Method in angular (Service)
GetPodForwardings(conNo,newPage,pageSize)
{
return this.http.get(`${this.BaseUrl}Pod/GetConsignmentList?conNo=${conNo}&newPage=${newPage}&pageSize=${pageSize}`)
}
In .NET Controller
[Microsoft.AspNetCore.Mvc.Route("GetConsignmentList")]
[HttpGet]
public async Task<IActionResult> GetListofConsignments([FromQuery]List<long> conNo,int currentPage,int pageSize)
{
return await ProcessQuery(new GetListofConsignmentByConsignmentNoQuery(conNo,currentPage,pageSize));
}
The proper way of adding parameters to an url in Angular is to use the second options parameter of the http.get("url",options) function. Unfortunatly they don't accept arrays rightaway (there is an open github issue).
However string interpolation like you did should also work. You seem to just have the wrong format. As this is treated very framework specific look at this answer to get the right format for your case.

query ravendb from web api 2 and return one document

I want to do the following using Asp.net Web API 2 and RavenDB.
Send a string to RavenDB.
Lookup a document containing a field called UniqueString that contain the string i passed to RavenDB.
Return either the document that matched, or a "YES/NO a document with that string exists" - message.
I am completely new to NoSQL and RavenDB, so this has proven to be quite difficult :-) I hope someone can assist me, and i assume it is actually quite easy to do though i haven't been able to find any guides showing it.
This has nothing to do with WebAPI 2, but you can do what you ask for using RavenDb combined with WebAPI 2.
First you need to have an index (or let RavenDb auto create one for you) on the document and property/properties you want to be indexed. This index can be created from code like this:
public class MyDocument_ByUniqueString : AbstractIndexCreationTask<MyDocument>
{
public override string IndexName
{
get { return "MyDocumentIndex/ByUniqueString"; }
}
public MyDocument_ByUniqueString()
{
Map = documents => from doc in documents
select new
{
doc.UniqueString
};
}
}
or created in the RavenDb Studio:
from doc in docs.MyDocuments
select new {
doc.UniqueString
}
After that you can do an "advanced document query" (from a WebAPI 2 controller or similar in your case) on that index and pass in a Lucene wildcard:
using (var session = documentStore.OpenSession())
{
var result = session.Advanced
.DocumentQuery<MyDocument>("MyDocumentIndex/ByUniqueString")
.Where("UniqueString: *uniq*")
.ToList();
}
This query will return all documents that has a property "UniqueString" that contains the term "uniq". The document in my case looked like this:
{
"UniqueString": "This is my unique string"
}
Please note however that these kind of wildcards in Lucene might not be super performant as they might need to scan large amount of texts. In the RavenDB documentation there's even a warning aginst this:
Warning
RavenDB allows to search by using such queries but you have to be
aware that leading wildcards drastically slow down searches. Consider
if you really need to find substrings, most cases looking for words is
enough. There are also other alternatives for searching without
expensive wildcard matches, e.g. indexing a reversed version of text
field or creating a custom analyzer.
http://ravendb.net/docs/article-page/2.0/csharp/client-api/querying/static-indexes/searching
Hope this helps!
Get the WebApi endpoint working to collect your input. This is independent of RavenDB.
Using the RavenDB client, query the database using Linq or one of the other methods.
After the document is retrieved you may need to write some logic to return the expected result.
I skipped the step where the database gets populated with the data to query. I would leverage the RavenDB client tools as much as possible in your app vs trying to use the HTTP api.

Web API and queries with foreign keys

I'm playing around with Web API, and I'm struggling a bit with creating queries to pull back data based on a filter. The classic example would be pulling back a list of items based on a foreign key.
Let's say I have the following entity:
Movie
======
id
directorId
categoryId
It would not be uncommon for me to build a DAO with the following methods:
MovieRepo.GetByDirector(int directoryId);
MovieRepo.GetByCategory(int category);
Recently, I have been using Linq and the Entity Framework to build retrieval methods that can be used by multiple calling clients, but whose returned list can filtered based on whatever criteria is passed to a filter
public IEnumerable<Movie> Get(MovieFilter filter){
IQueryable<Movie> query = _context.tblMovie;
if(!String.IsNullOrEmpty(filter.directorId))
query.Where(m => m.directoryId == filter.directorId);
if(!String.IsNullOrEmpty(filter.categoryId))
query.Where(m => m.categoryId == filter.categoryId);
return query.ToList();
}
The boilerplate Web API controller actions are:
IEnumerable<Movie> Get();
Movie Get(int id)
If I wanted to filter my query by directory or category with Web API, how exactly would I do it in a RESTful way? Given the way routing gets resolved, the following would be an ambiguous call:
IEnumerable<Movie> GetByCategory(int categoryId);
I haven't see much guidance on this, can someone provide some for me?
Regards,
Chris
One of the ways is to use OData protocol http://www.odata.org/docs/
There is also a library supporting OData filtering http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api, supporting querying over the IQueryable interface
It could be seen as a bit more complex, but you gain a lot. Parts of the OData standard :
$filter - Filters the results, based on a Boolean condition.
$select - which columns/properties should be selected
$inlinecount - Tells the server to include the total count of matching entities in the response. (Useful for server-side paging.)
$orderby - Sorts the results.
$skip - Skips the first n results.
$top - Returns only the first n the results.
Honestly, we are using the OData ... while not using the IQueryable and MS libraries. We just created own parser, supporting only limited stuff. But there is OData standard in place

Remove field in wsdl in Asp.net webservice

I'm generating dto classes with a template engine and would like to exclude some properties in an asmx webservice, what, if possible, is the best way to do this?
Ex:
[WebMethod]
public ProductPackages GetPackages()
{
ProductPackages packages = new ProductPackages();
packages.Packages.add(new PackageDTO());
return packages;
}
The PackageDTO contains some properties that's not relevant for this service.
But as the class can be regenerated any time i can't apply [XmlIgnore] to the fields.
So I'm looking for a way to apply a "exclude list" without touching the actual class.
Above is just an example, the template engine generates dto's for all tables in a given project, and I would like to be able to use them in services without needing to maintain a big bunch of nearly identical classes.
Just hit the same problem. You can exclude fields by marking them as internal.
public class Order
{
public double OrderPrice;
internal double ProfitMargin;
internal string TheTruthAboutThisCustomer;
}
If you don't want to return a field or property, then don't have it in the object you return! It's as simple as that.

How to consume data from an ASP.NET MVC from a different website?

I am playing around with ASP.NET MVC for the first time, so I apologize in advance if this sounds academic.
I have created a simple content management system using ASP.NET MVC. The url to retrieve a list of content, in this case, announcements, looks like:
http://www.mydomain.com/announcements/list/10
This will return the top ten most recent announcements.
My questions are as follows:
Is it possible for any website to consume this service? Or would I also have to expose it using something like WCF?
What are some examples, of how to consume this service to display this data on another website? I'm primarily programming in the .NET world, but I'm thinking if I could consume the service using javascript, or do something with Json, it could really work for any technology.
I am looking to dynamically generate something like the following output:
<div class="announcement">
<h1>Title</h1>
<h2>Posted Date</h3>
<p>Teaser</p>
More
</div>
For now ... is it possible to return an Html representation and display it in a webpage? Is this possible using just Javascript?
There is nothing to stop another client just scraping that particular page and parsing through your HTML.
However you would probably want another view using the same controller that generates the data that doesnt contain excess formatting HTML etc. Maybe look at using a well known format such as RSS?
You can return the result as JSON using something like below:
public JsonResult GetResults()
{
return Json(new { message = "SUCCESS" });
}
I think I would offer a view which contains the items as xml and another that returns JSON that way you have the best of both worlds.
I have a small post about how to call and return something using MVC, JQuery and JSON here.
Your ROUTE is perfectly fine and consumable by anyone. The trick is to how you want to expose your data for that route. You said XML. sure. You can even do JSon or Html or just plain ole text.
The trick would be in your controller Method and the view result object.
Here's the list of main view results :-
ActionResult
ContentResult
EmptyResult
JsonResult
RedirectResult
eg.
public <ContentResult> AnnouncmentIndex(int numberOfAnnouncements)
{
// Generate your Xml dynamically.
string xml = "<div class=\"announcement\"><h1>Title</h1><h2>Posted Date</h3><p>Teaser</p>More</div>"
Response.ContentType = "application/xml"; // For extra bonus points!
return Content(xml);
}

Resources