<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Giventocode</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/giventocode/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/giventocode/feed.xml</link>
    <description>Jesus Aguilar, Technical Evangelist at Microsoft</description>
    <lastBuildDate>Wed, 17 Apr 2019 03:23:07 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Hacking NYC restaurant ratings using Azure Machine Learning</title>
      <link>https://docs.microsoft.com/archive/blogs/giventocode/hacking-nyc-restaurant-ratings-using-azure-machine-learning</link>
      <pubDate>Sun, 10 May 2015 08:19:29 GMT</pubDate>
      <dc:creator><![CDATA[giventocode]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/giventocode/2015/05/10/hacking-nyc-restaurant-ratings-using-azure-machine-learning/</guid>
      <description><![CDATA[I delivered a session on Azure ML at the recent NYCMicrosoft BigData hackathon. I had a great time...]]></description>
      <content:encoded><![CDATA[<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/f9f79f070069_8D0D/image_thumb.png"><img style="max-width: 550px;" src="http://giventocode.com/Media/Default/Windows-Live-Writer/f9f79f070069_8D0D/image_thumb.png" alt="" border="0" /></a></p>
<p>I delivered a session on Azure ML at the recent NYC<br />Microsoft BigData hackathon. I had a great time exploring exciting machine<br />learning scenarios and ideas with the attendees. Later in the day, while the<br />teams were heads down working on their projects, I had open time to do some<br />Azure ML hacking using the New York City restaurant inspection results dataset.</p>
<p>The gist of the idea was to create a model that can predict<br />the grade of a restaurant from the description of the violation. The results<br />were remarkably accurate, so I am sharing the approach, and this is the<br />walkthrough.</p>
<p>Read more <a href="http://giventocode.com/hacking-nyc-restaurant-ratings-using-azure-machine-learning#.VU91Bo1TH4g">here</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Using Azure Search in Your ASP.NET MVC Website</title>
      <link>https://docs.microsoft.com/archive/blogs/giventocode/using-azure-search-in-your-asp-net-mvc-website</link>
      <pubDate>Wed, 28 Jan 2015 08:29:00 GMT</pubDate>
      <dc:creator><![CDATA[giventocode]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/giventocode/2015/01/28/using-azure-search-in-your-asp-net-mvc-website/</guid>
      <description><![CDATA[Consider a scenario where you have a database-driven website and you want to enable full text search...]]></description>
      <content:encoded><![CDATA[<p>Consider a scenario where you have a database-driven website and you want to enable full text search based on the data stored in your data back end. Typically, approaches to fulfill this scenario consist of using the database&rsquo;s full text search capabilities or setting up third-party components that, in turn, you need to manage. In both cases, if you need to scale out, maintaining the search index (containing the searchable data of your application) becomes a challenging endeavor.</p>
<h3>Enter Azure Search</h3>
<p>Azure Search is a platform-as-a-service offering that handles the hurdles of maintaining a search index while giving you full flexibility to define the index and scale out when you need more resources and scale down when you don&rsquo;t need them anymore. <a href="http://giventocode.com/full-text-search-for-your-back-end-using-azure-search-and-azure-mobile-services#.VMkP1Y1THIU" target="_blank">In my last post</a>, I described how you can enable full text search for an Azure Mobile Services back end. As a continuation of the theme, I thought it would be useful to showcase how you can enable a similar functionality for a database-driven ASP.NET website. So let&rsquo;s get to it.</p>
<h3>Revisiting the Basics</h3>
<p>Similar to the previous post, this process consists of creating an index, then enqueueing data changes and having a process that reads from the queue and updates the index.</p>
<p>We will also use the Azure Service Bus&rsquo;s queue (hence guaranteeing orderly delivery) and an attribute-based implementation to tag the data entities with metadata. The metadata defines the index&rsquo;s schema and the properties that will be written to the index. In this instance, we will leverage an Azure WebJob to perform the index operations.</p>
<h4>&nbsp;</h4>
<h3>Prerequisites</h3>
<p>To follow the steps below, you need to download and make a reference to the project that contains the attribute and infrastructure code. You can get it <a href="https://github.com/giventocode/asp-mvc-azuresearch/tree/master/azuresearch-entitymanager/Giventocode.AzureSearchEntityManager" target="_blank">here</a>. Also, I am assuming that you already have an instance of Azure Search and Azure Service Bus running. For more information about getting started with Azure Search, see <a href="http://azure.microsoft.com/en-us/documentation/articles/search-get-started/">this article</a>.</p>
<h4>&nbsp;</h4>
<h3>Building Our Model and Capturing Changes</h3>
<p>In an empty ASP.NET MVC website, let&rsquo;s create a model and decorate it with the custom Azure Search attribute.</p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; background-color: #f4f4f4; border-style: none; padding: 0px;"><span style="color: #0000ff;">namespace</span> aspnet_mvc_azuresearch.Models<br />{<br />    <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> RockBand<br />    {<br />        [Indexable(<span style="color: #006080;">"Edm.String"</span>, <span style="color: #0000ff;">false</span>, Key = <span style="color: #0000ff;">true</span>, Name = <span style="color: #006080;">"id"</span>)]<br />        <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Id { get; set; }<br /><br />        [Indexable(<span style="color: #006080;">"Edm.String"</span>, <span style="color: #0000ff;">true</span>, Name = <span style="color: #006080;">"name"</span>, Retrievable=<span style="color: #0000ff;">true</span>)]        <br />        <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Name { get; set; }<br /><br />        [Indexable(<span style="color: #006080;">"Edm.String"</span>, <span style="color: #0000ff;">true</span>, Name = <span style="color: #006080;">"genre"</span>, Retrievable = <span style="color: #0000ff;">true</span>)]<br />        <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Genre { get; set; }<br /><br />        [Indexable(<span style="color: #006080;">"Edm.String"</span>, <span style="color: #0000ff;">true</span>, Name = <span style="color: #006080;">"description"</span>, Retrievable = <span style="color: #0000ff;">true</span>)]<br />        <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Description { get; set;}<br />    }<br />}</pre>
</div>
<p>Next, using the scaffolding capabilities of Visual Studio, let&rsquo;s wire up a controller with Entity Framework and the corresponding write, edit, delete, and list views.</p>
<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/e527bdaad30b_8395/image_2.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/e527bdaad30b_8395/image_thumb.png" alt="image" width="640" height="441" border="0" /></a></p>
<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/e527bdaad30b_8395/image_4.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/e527bdaad30b_8395/image_thumb_1.png" alt="image" width="640" height="405" border="0" /></a></p>
<p>It&rsquo;s considered a best practice to implement a view model between your view and your entities. But for simplicity, we will use the scaffolded code as is.</p>
<p>Let&rsquo;s include the code (highlighted below) in the applicable actions that will send the entity changes to the queue .</p>
<div id="codeSnippetWrapper">
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; background-color: #f4f4f4; border-style: none; padding: 0px;"><span style="color: #0000ff;">namespace</span> aspnet_mvc_azuresearch.Controllers<br />{<br />    <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> RockBandsController : Controller<br />    {<br />...      <br />        </pre>
<span style="background-color: #ffff00;"><span style="color: #0000ff;">private</span> IndexManager ixMan = <span style="color: #0000ff;">new</span> IndexManager();</span>
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; background-color: #f4f4f4; border-style: none; padding: 0px;"><br /><br />        ...<br />        <br />        <span style="color: #008000;">// POST: RockBands/Create</span><br />        <span style="color: #008000;">// To protect from overposting attacks, please enable the specific properties you want to bind to, for </span><br />        <span style="color: #008000;">// more details see http://go.microsoft.com/fwlink/?LinkId=317598.</span><br />        [HttpPost]<br />        [ValidateAntiForgeryToken]<br />        <span style="color: #0000ff;">public</span> ActionResult Create([Bind(Include = <span style="color: #006080;">"Id,Name,Genre,Description"</span>)] RockBand rockBand)<br />        {<br />            <span style="color: #0000ff;">if</span> (ModelState.IsValid)<br />            {<br />                db.RockBands.Add(rockBand);<br />                db.SaveChanges();<br />                </pre>
<span style="background-color: #ffff00;">ixMan.EnqueueEntity&lt;RockBand&gt;(rockBand, <span style="color: #006080;">"upload"</span>);<br /></span>
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; background-color: #f4f4f4; border-style: none; padding: 0px;">                <span style="color: #0000ff;">return</span> RedirectToAction(<span style="color: #006080;">"Index"</span>);<br />            }<br /><br />            <span style="color: #0000ff;">return</span> View(rockBand);<br />        }<br /><br /><br />        <span style="color: #008000;">// POST: RockBands/Edit/5</span><br />        <span style="color: #008000;">// To protect from overposting attacks, please enable the specific properties you want to bind to, for </span><br />        <span style="color: #008000;">// more details see http://go.microsoft.com/fwlink/?LinkId=317598.</span><br />        [HttpPost]<br />        [ValidateAntiForgeryToken]<br />        <span style="color: #0000ff;">public</span> ActionResult Edit([Bind(Include = <span style="color: #006080;">"Id,Name,Genre,Description"</span>)] RockBand rockBand)<br />        {<br />            <span style="color: #0000ff;">if</span> (ModelState.IsValid)<br />            {<br />                db.Entry(rockBand).State = EntityState.Modified;<br />                db.SaveChanges();<br />                </pre>
<span style="background-color: #ffff00;">ixMan.EnqueueEntity&lt;RockBand&gt;(rockBand, <span style="color: #006080;">"merge"</span>);</span>
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; background-color: #f4f4f4; border-style: none; padding: 0px;"><br />                <span style="color: #0000ff;">return</span> RedirectToAction(<span style="color: #006080;">"Index"</span>);<br />            }<br />            <span style="color: #0000ff;">return</span> View(rockBand);<br />        }<br /><br />        <span style="color: #008000;">// POST: RockBands/Delete/5</span><br />        [HttpPost, ActionName(<span style="color: #006080;">"Delete"</span>)]<br />        [ValidateAntiForgeryToken]<br />        <span style="color: #0000ff;">public</span> ActionResult DeleteConfirmed(<span style="color: #0000ff;">string</span> id)<br />        {<br />            RockBand rockBand = db.RockBands.Find(id);<br />            db.RockBands.Remove(rockBand);<br />            db.SaveChanges();<br />           </pre>
<span style="background-color: #ffff00;"> ixMan.EnqueueEntity&lt;RockBand&gt;(rockBand, <span style="color: #006080;">"delete"</span>);</span>
<pre id="codeSnippet" style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; background-color: #f4f4f4; border-style: none; padding: 0px;"><br />            <span style="color: #0000ff;">return</span> RedirectToAction(<span style="color: #006080;">"Index"</span>);<br />        }<br /><br />        ...<br /><br />    }<br />}</pre>
</div>
<p>In the WebConfig, you need to add the following settings:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="214">
<p><strong>Setting Name</strong></p>
</td>
<td valign="top" width="211">
<p><strong>Value</strong></p>
</td>
</tr>
<tr>
<td valign="top" width="214">
<p><strong>ASEM_SbConnString</strong></p>
</td>
<td valign="top" width="211">
<p>Endpoint to the service bus instance that contains the queue. More information <a href="http://azure.microsoft.com/en-us/documentation/articles/service-bus-dotnet-how-to-use-queues/">here</a></p>
</td>
</tr>
<tr>
<td valign="top" width="214">
<p><strong>ASEM_SearchServiceName</strong></p>
</td>
<td valign="top" width="211">
<p>Name of the search service</p>
</td>
</tr>
<tr>
<td valign="top" width="214">
<p><strong>ASEM_IndexName</strong></p>
</td>
<td valign="top" width="211">
<p>The desired index name that will be created and used by the solution</p>
</td>
</tr>
<tr>
<td valign="top" width="214">
<p><strong>ASEM_ApiVersion</strong></p>
</td>
<td valign="top" width="211">
<p>Azure Search API version. See <a href="https://msdn.microsoft.com/en-us/library/azure/dn864560.aspx">Search Service Version</a> for details</p>
</td>
</tr>
<tr>
<td valign="top" width="214">
<p><strong>ASEM_ApiKey</strong></p>
</td>
<td valign="top" width="211">
<p>API key to call the Azure Search service</p>
</td>
</tr>
</tbody>
</table>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; background-color: #f4f4f4; border-style: none; padding: 0px;"><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">appSettings</span><span style="color: #0000ff;">&gt;</span><br />    ...<br />    <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">add</span> <span style="color: #ff0000;">key</span><span style="color: #0000ff;">="ASEM_SbConnString"</span> <span style="color: #ff0000;">value</span><span style="color: #0000ff;">="YOUR SERVICE BUS CONNECTION STRING"</span><span style="color: #0000ff;">/&gt;</span><br />    <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">add</span> <span style="color: #ff0000;">key</span><span style="color: #0000ff;">="ASEM_SearchServiceName"</span> <span style="color: #ff0000;">value</span><span style="color: #0000ff;">="giventocodems"</span><span style="color: #0000ff;">/&gt;</span><br />    <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">add</span> <span style="color: #ff0000;">key</span><span style="color: #0000ff;">="ASEM_IndexName"</span> <span style="color: #ff0000;">value</span><span style="color: #0000ff;">="ixrockbands"</span><span style="color: #0000ff;">/&gt;</span><br />    <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">add</span> <span style="color: #ff0000;">key</span><span style="color: #0000ff;">="ASEM_ApiVersion"</span> <span style="color: #ff0000;">value</span><span style="color: #0000ff;">="2014-10-20-Preview"</span><span style="color: #0000ff;">/&gt;</span><br />    <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">add</span> <span style="color: #ff0000;">key</span><span style="color: #0000ff;">="ASEM_ApiKey"</span> <span style="color: #ff0000;">value</span><span style="color: #0000ff;">="YOUR AZURE SEARCH API KEY"</span><span style="color: #0000ff;">/&gt;</span><br />  <span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">appSettings</span><span style="color: #0000ff;">&gt;</span></pre>
</div>
<h4>&nbsp;</h4>
<h3>Search Results</h3>
<p>Next, let&rsquo;s create a search user interface and we will start with a new view model.</p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; background-color: #f4f4f4; border-style: none; padding: 0px;"><span style="color: #0000ff;">namespace</span> aspnet_mvc_azuresearch.Models<br />{<br /><br />    <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> SearchViewModel<br />    {<br />        <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Criteria { get; set; }<br />        <span style="color: #0000ff;">public</span> SearchResultViewModel[] Results { get; set; }<br />    }<br /><br />    <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> SearchResultViewModel<br />    {<br />        <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Id { get; set; }<br />        <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Name { get; set; }<br />        <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Description { get; set; }<br />        <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Genre { get; set; }<br />    }<br />}</pre>
</div>
<p>Add a view for our view model.</p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; background-color: #f4f4f4; border-style: none; padding: 0px;">@model aspnet_mvc_azuresearch.Models.SearchViewModel<br /><br />@{<br />    ViewBag.Title = "Index";<br />    Layout = "~/Views/Shared/_Layout.cshtml";<br />}<br /><br /><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">h2</span><span style="color: #0000ff;">&gt;</span>Search<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">h2</span><span style="color: #0000ff;">&gt;</span><br /><br /><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">p</span><span style="color: #0000ff;">&gt;</span><br />    @using (Html.BeginForm("","Search",FormMethod.Get))<br />    {<br />       <br /><br />        <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">div</span> <span style="color: #ff0000;">class</span><span style="color: #0000ff;">="form-horizontal"</span><span style="color: #0000ff;">&gt;</span><br />            <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">h4</span><span style="color: #0000ff;">&gt;</span>RockBand Search<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">h4</span><span style="color: #0000ff;">&gt;</span><br />            <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">hr</span> <span style="color: #0000ff;">/&gt;</span><br />            <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">div</span> <span style="color: #ff0000;">class</span><span style="color: #0000ff;">="form-group"</span><span style="color: #0000ff;">&gt;</span><br />                @Html.LabelFor(model =<span style="color: #0000ff;">&gt;</span> model.Criteria, htmlAttributes: new { @class = "control-label col-md-2" })<br />                <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">div</span> <span style="color: #ff0000;">class</span><span style="color: #0000ff;">="col-md-10"</span><span style="color: #0000ff;">&gt;</span><br />                    @Html.EditorFor(model =<span style="color: #0000ff;">&gt;</span> model.Criteria, new { htmlAttributes = new { @class = "form-control" } })                    <br />                <span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">div</span><span style="color: #0000ff;">&gt;</span><br />            <span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">div</span><span style="color: #0000ff;">&gt;</span><br /><br />            <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">div</span> <span style="color: #ff0000;">class</span><span style="color: #0000ff;">="form-group"</span><span style="color: #0000ff;">&gt;</span><br />                <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">div</span> <span style="color: #ff0000;">class</span><span style="color: #0000ff;">="col-md-offset-2 col-md-10"</span><span style="color: #0000ff;">&gt;</span><br />                    <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">input</span> <span style="color: #ff0000;">type</span><span style="color: #0000ff;">="submit"</span> <span style="color: #ff0000;">value</span><span style="color: #0000ff;">="Search"</span> <span style="color: #ff0000;">class</span><span style="color: #0000ff;">="btn btn-default"</span> <span style="color: #0000ff;">/&gt;</span><br />                <span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">div</span><span style="color: #0000ff;">&gt;</span><br />            <span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">div</span><span style="color: #0000ff;">&gt;</span><br />        <span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">div</span><span style="color: #0000ff;">&gt;</span><br />    }<br /><br /><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">p</span><span style="color: #0000ff;">&gt;</span><br /><br /><br /><br /><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">ul</span><span style="color: #0000ff;">&gt;</span><br />    @foreach (var item in Model.Results)<br />    {<br />        <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">li</span><span style="color: #0000ff;">&gt;</span><br />            <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">strong</span><span style="color: #0000ff;">&gt;</span>@Html.DisplayFor(model =<span style="color: #0000ff;">&gt;</span> item.Name)<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">strong</span><span style="color: #0000ff;">&gt;</span><br />            <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">p</span><span style="color: #0000ff;">&gt;</span><br />                <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">small</span><span style="color: #0000ff;">&gt;</span>Genre: @Html.DisplayFor(model =<span style="color: #0000ff;">&gt;</span> item.Genre)<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">small</span><span style="color: #0000ff;">&gt;</span><br />            <span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">p</span><span style="color: #0000ff;">&gt;</span><br />            <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">p</span><span style="color: #0000ff;">&gt;</span><br />                @Html.DisplayFor(model =<span style="color: #0000ff;">&gt;</span> item.Description)<br />            <span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">p</span><span style="color: #0000ff;">&gt;</span><br />            <br />        <span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">li</span><span style="color: #0000ff;">&gt;</span>        <br />    }<br /><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">ul</span><span style="color: #0000ff;">&gt;</span></pre>
</div>
<p>And the search controller.</p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; background-color: #f4f4f4; border-style: none; padding: 0px;"><span style="color: #0000ff;">namespace</span> aspnet_mvc_azuresearch.Controllers<br />{<br />    <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> SearchController : Controller<br />    {<br />        <span style="color: #0000ff;">private</span> AzureSearchManager searchMan = <span style="color: #0000ff;">new</span> AzureSearchManager();<br />        <br />        [HttpGet]<br />        <span style="color: #0000ff;">public</span> async Task&lt;ActionResult&gt; Index(<span style="color: #0000ff;">string</span> criteria) <br />        {<br /><br />            <span style="color: #0000ff;">if</span> (<span style="color: #0000ff;">string</span>.IsNullOrEmpty(criteria))<br />            {<br />                <span style="color: #0000ff;">return</span> View(<span style="color: #0000ff;">new</span> SearchViewModel() { Results = <span style="color: #0000ff;">new</span> SearchResultViewModel[0] });<br />            }<br /><br />            var results = await searchMan.SearchAsync(criteria);<br />            var resultsVM = ((JArray)results[<span style="color: #006080;">"value"</span>])<br />                            .Select&lt;JToken, SearchResultViewModel&gt;(t =&gt; <span style="color: #0000ff;">new</span> SearchResultViewModel() { Id = (<span style="color: #0000ff;">string</span>)t[<span style="color: #006080;">"id"</span>], Name = (<span style="color: #0000ff;">string</span>)t[<span style="color: #006080;">"name"</span>], Genre = (<span style="color: #0000ff;">string</span>)t[<span style="color: #006080;">"genre"</span>], Description = (<span style="color: #0000ff;">string</span>)t[<span style="color: #006080;">"description"</span>] })<br />                            .ToArray&lt;SearchResultViewModel&gt;();<br /><br />            <span style="color: #0000ff;">return</span> View(<span style="color: #0000ff;">new</span> SearchViewModel() { Results = resultsVM });<br />        }<br />    }<br />}</pre>
</div>
<h4>&nbsp;</h4>
<h4>Processing Changes and Index Operations</h4>
<p>Finally, we need to implement the process that will read the messages from the queue and perform the index operations. For this, we will use an Azure WebJob using the WebJobs SDK. By using the SDK, we don&rsquo;t need to implement polling logic because it provides built-in capabilities to trigger the WebJob when new messages arrive automatically. So let&rsquo;s add a new Azure WebJob project to our solution.</p>
<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/e527bdaad30b_8395/image_6.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/e527bdaad30b_8395/image_thumb_2.png" alt="image" width="640" height="390" border="0" /></a></p>
<p>After adding a reference to the AzureEntityManager project, let&rsquo;s add a function that receives the message from the queue and performs the corresponding index operation.</p>
<blockquote>
<p><span style="font-size: x-small;"><strong>Note:</strong> The AzureSearchManager, before performing the corresponding index operation, checks if the index exists, and if it doesn&rsquo;t, it creates one according to the attributes defined in the data entity.</span></p>
</blockquote>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; background-color: #f4f4f4; border-style: none; padding: 0px;"><span style="color: #0000ff;">namespace</span> Giventocode.AzureSearchWebJob<br />{<br />    <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> Functions<br />    {<br />        <span style="color: #008000;">// This function will get triggered/executed when a new message is written </span><br />        <span style="color: #008000;">// on an Azure Queue called queue.</span><br />        <br />        <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> async Task IndexEntity( [ServiceBusTrigger(IndexManager.INDEXER_QUEUE)] <span style="color: #0000ff;">string</span> msg ,<br />             TextWriter log) <br />         {<br />             var searchMan = <span style="color: #0000ff;">new</span> AzureSearchManager();              <br />             <br />             await searchMan.IndexDocumentAsync(msg);<br />         } <br /><br />    }<br />}</pre>
</div>
<p>Azure WebJob require a storage account where execution logs will be stored, and in the configuration file, you must include the connection string to the storage account and the service bus instance that contains the queue.</p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; background-color: #f4f4f4; border-style: none; padding: 0px;"><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">connectionStrings</span><span style="color: #0000ff;">&gt;</span><br />   <span style="color: #008000;">&lt;!-- The format of the connection string is "DefaultEndpointsProtocol=https;AccountName=NAME;AccountKey=KEY" --&gt;</span><br />   <span style="color: #008000;">&lt;!-- For local execution, the value can be set either in this config file or through environment variables --&gt;</span><br />   <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">add</span> <span style="color: #ff0000;">name</span><span style="color: #0000ff;">="AzureWebJobsDashboard"</span> <span style="color: #ff0000;">connectionString</span><span style="color: #0000ff;">="YOUR STORAGE ACCOUNT CONNECTION STRING"</span> <span style="color: #0000ff;">/&gt;</span><br />   <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">add</span> <span style="color: #ff0000;">name</span><span style="color: #0000ff;">="AzureWebJobsStorage"</span> <span style="color: #ff0000;">connectionString</span><span style="color: #0000ff;">="YOUR STORAGE ACCOUNT CONNECTION STRING"</span> <span style="color: #0000ff;">/&gt;</span><br />   <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">add</span> <span style="color: #ff0000;">name</span><span style="color: #0000ff;">="AzureWebJobsServiceBus"</span> <span style="color: #ff0000;">connectionString</span><span style="color: #0000ff;">="YOUR SERVICE BUS CONNECTION STRING"</span> <span style="color: #0000ff;">/&gt;</span><br /><br /> <span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">connectionStrings</span><span style="color: #0000ff;">&gt;</span></pre>
</div>
<p>We also need to add the AzureEntityManager settings to the App.config.</p>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; background-color: #f4f4f4; border-style: none; padding: 0px;"><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">appSettings</span><span style="color: #0000ff;">&gt;</span><br />   <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">add</span> <span style="color: #ff0000;">key</span><span style="color: #0000ff;">="ASEM_SearchServiceName"</span> <span style="color: #ff0000;">value</span><span style="color: #0000ff;">="giventocodems"</span><span style="color: #0000ff;">/&gt;</span><br />   <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">add</span> <span style="color: #ff0000;">key</span><span style="color: #0000ff;">="ASEM_IndexName"</span> <span style="color: #ff0000;">value</span><span style="color: #0000ff;">="ixrockbands"</span><span style="color: #0000ff;">/&gt;</span><br />   <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">add</span> <span style="color: #ff0000;">key</span><span style="color: #0000ff;">="ASEM_ApiVersion"</span> <span style="color: #ff0000;">value</span><span style="color: #0000ff;">="2014-10-20-Preview"</span><span style="color: #0000ff;">/&gt;</span><br />   <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">add</span> <span style="color: #ff0000;">key</span><span style="color: #0000ff;">="ASEM_ApiKey"</span> <span style="color: #ff0000;">value</span><span style="color: #0000ff;">="YOUR AZURE SEARCH API KEY"</span><span style="color: #0000ff;">/&gt;</span><br /> <span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">appSettings</span><span style="color: #0000ff;">&gt;</span></pre>
</div>
<h4>&nbsp;</h4>
<h4>Running with It!</h4>
<p>We are now ready to run the website. So let&rsquo;s create a new entry and then edit its description.</p>
<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/e527bdaad30b_8395/image_12.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/e527bdaad30b_8395/image_thumb_5.png" alt="image" width="473" height="480" border="0" /></a></p>
<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/e527bdaad30b_8395/image_14.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/e527bdaad30b_8395/image_thumb_6.png" alt="image" width="472" height="480" border="0" /></a></p>
<p>&nbsp;</p>
<p>After running the web job, we can see that it processed two messages: upload (insert) and then merge (update) operations.</p>
<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/e527bdaad30b_8395/image_10.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/e527bdaad30b_8395/image_thumb_4.png" alt="image" width="640" height="324" border="0" /></a></p>
<p>Search for using a keyword from the updated description and results!</p>
<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/e527bdaad30b_8395/image_16.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/e527bdaad30b_8395/image_thumb_7.png" alt="image" width="473" height="480" border="0" /></a></p>
<p>If we go to the Azure preview portal, we can see the newly created index and our document.</p>
<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/e527bdaad30b_8395/image_18.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/e527bdaad30b_8395/image_thumb_8.png" alt="image" width="644" height="336" border="0" /></a></p>
<h4>&nbsp;</h4>
<h4>Final Thoughts</h4>
<p>It is worth mentioning that this approach is suitable for on-premises scenarios. So you can have your website hosted outside of Azure&mdash;and the WebJob and Azure Search service running on Azure. In addition, you can implement your own queue processing job easily. To facilitate this task, the IndexManager exposes a method that reads from the service bus queue and performs the index operation accordingly.</p>
<p>Also, you can download the full solution from <a href="https://github.com/giventocode/asp-mvc-azuresearch" target="_blank">here</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Full-text search for your back-end using Azure Search and Azure Mobile Services</title>
      <link>https://docs.microsoft.com/archive/blogs/giventocode/full-text-search-for-your-back-end-using-azure-search-and-azure-mobile-services</link>
      <pubDate>Wed, 05 Nov 2014 17:18:30 GMT</pubDate>
      <dc:creator><![CDATA[giventocode]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/giventocode/2014/11/05/full-text-search-for-your-back-end-using-azure-search-and-azure-mobile-services/</guid>
      <description><![CDATA[&nbsp; In a previous blog post, I described implementation of full-text search capabilities for your...]]></description>
      <content:encoded><![CDATA[<p>&nbsp; <p>In a <a href="http://giventocode.com/how-to-implement-full-text-search-in-your-mobile-application-using-azure-mobile-services#.VFrDrI3wvIU" target="_blank">previous blog post</a>, I described implementation of full-text search capabilities for your Azure Mobile Services back-end. With the recent availability of Azure Search —search as a service in Azure— I thought it would be useful to revisit the idea and modify it using this cool new Azure capability.  <p>&nbsp;</p> <div style="font-size: 11px; max-width: 529px; font-family: 'Helvetica Neue',arial,sans-serif; width: 100%; color: #a7a7a7; display: inline-block; background-color: #fff"> <div style="overflow: hidden; height: 0px; width: 100%; position: relative; padding-bottom: 0px; padding-top: 61.24%; padding-left: 0px; padding-right: 0px"><iframe style="height: 100%; width: 100%; position: absolute; left: 0px; display: inline-block; top: 0px" height="324" src="http://blogs.msdn.com//embed.gettyimages.com/embed/481668757?et=-tEH9RoaTURK239rqSeHYQ&amp;similar=off&amp;sig=Vg0fyCXBWdmHPCOX2suLYgmKcLrSm1FrpJmLpGt4NgI=" frameborder="0" width="529" scrolling="no"></iframe></div> <p style="margin: 0px"></p> <div style="padding-bottom: 0px; text-align: left; padding-top: 0px; padding-left: 0px; margin: 0px 0px 0px 10px; padding-right: 0px"><a style="text-decoration: none; border-top: medium none; border-right: medium none; border-bottom: medium none; font-weight: normal !important; color: #a7a7a7; border-left: medium none; display: inline-block" href="http://www.gettyimages.com/detail/481668757" target="_blank">#481668757</a> / <a style="text-decoration: none; border-top: medium none; border-right: medium none; border-bottom: medium none; font-weight: normal !important; color: #a7a7a7; border-left: medium none; display: inline-block" href="http://www.gettyimages.com" target="_blank">gettyimages.com</a></div></div> <h3>&nbsp;</h3> <h3>Defining the Index’s Schema</h3> <p>A document is the basic unit of data in Azure Search. Each document contains a set of fields, and each field has a set of attributes that define how the index handles the data associated which each field. When we create an index in Azure Search, we must create a schema that outlines attributes for each field. In the schema, we outline the types of fields available, which fields are searchable, and other interesting field capabilities. For example, we determine whether a field can be used as a search suggestion, for ordering or filtering the results, and as a facet, such as showing a count of results by brand if you search for “sports cars.”  <p>&nbsp; <blockquote> <p><font size="2">Note: For more information about the schema definition, click <a href="http://msdn.microsoft.com/en-us/library/azure/dn798941.aspx" target="_blank">here</a>.</font></p></blockquote> <p>Following the spirit of a “code first” approach, let’s create a custom attribute that models the attributes of the index. We can then use it in the properties of an entity to create the metadata that will define the schema of the index.  <div id="codeSnippetWrapper"><pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; border-left-style: none; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4">[AttributeUsage(AttributeTargets.Property)]<br>    <span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> IndexableAttribute : Attribute<br>    {<br><br>        <span style="color: #0000ff">private</span> <span style="color: #0000ff">string</span> _name;<br><br>        <span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> Name<br>        {<br>            get { <span style="color: #0000ff">return</span> _name; }<br>            set { _name = <span style="color: #0000ff">value</span>; }<br>        }<br><br>        <span style="color: #0000ff">public</span> <span style="color: #0000ff">readonly</span> <span style="color: #0000ff">string</span> Type;<br>        <span style="color: #0000ff">public</span> <span style="color: #0000ff">readonly</span> <span style="color: #0000ff">bool</span> Searchable;<br>        <br>        <span style="color: #0000ff">private</span> <span style="color: #0000ff">bool</span> _filterable = <span style="color: #0000ff">true</span>;<br><br>        <span style="color: #0000ff">public</span> <span style="color: #0000ff">bool</span> Filterable<br>        {<br>            get { <span style="color: #0000ff">return</span> _filterable; }<br>            set { _filterable = <span style="color: #0000ff">value</span>; }<br>        }<br><br>        <span style="color: #0000ff">private</span> <span style="color: #0000ff">bool</span> _sortable = <span style="color: #0000ff">true</span>;<br><br>        <span style="color: #0000ff">public</span> <span style="color: #0000ff">bool</span> Sortable<br>        {<br>            get { <span style="color: #0000ff">return</span> _sortable; }<br>            set { _sortable = <span style="color: #0000ff">value</span>; }<br>        }<br><br><br>        <span style="color: #0000ff">private</span> <span style="color: #0000ff">bool</span> _facetable = <span style="color: #0000ff">true</span>;<br><br>        <span style="color: #0000ff">public</span> <span style="color: #0000ff">bool</span> Facetable<br>        {<br>            get { <span style="color: #0000ff">return</span> _facetable; }<br>            set { _facetable = <span style="color: #0000ff">value</span>; }<br>        }<br><br><br>        <span style="color: #0000ff">private</span> <span style="color: #0000ff">bool</span> _suggestions = <span style="color: #0000ff">false</span>;<br><br>        <span style="color: #0000ff">public</span> <span style="color: #0000ff">bool</span> Suggestions<br>        {<br>            get { <span style="color: #0000ff">return</span> _suggestions; }<br>            set { _suggestions = <span style="color: #0000ff">value</span>; }<br>        }<br><br>        <span style="color: #0000ff">private</span> <span style="color: #0000ff">bool</span> _key = <span style="color: #0000ff">false</span>;<br><br>        <span style="color: #0000ff">public</span> <span style="color: #0000ff">bool</span> Key<br>        {<br>            get { <span style="color: #0000ff">return</span> _key; }<br>            set { _key = <span style="color: #0000ff">value</span>; }<br>        }<br><br><br>        <span style="color: #0000ff">private</span> <span style="color: #0000ff">bool</span> _retrievable = <span style="color: #0000ff">false</span>;<br><br>        <span style="color: #0000ff">public</span> <span style="color: #0000ff">bool</span> Retrievable<br>        {<br>            get { <span style="color: #0000ff">return</span> _retrievable; }<br>            set { _retrievable = <span style="color: #0000ff">value</span>; }<br>        }<br><br>        <span style="color: #0000ff">public</span> IndexableAttribute(<span style="color: #0000ff">string</span> type, <span style="color: #0000ff">bool</span> searchable )<br>        {            <br>            <span style="color: #0000ff">this</span>.Type = type;<br>            <span style="color: #0000ff">this</span>.Searchable = searchable;<br>        }<br>    }</pre><br></div>
<h3>Capturing Changes </h3>
<p>Whenever an entity is modified or created, we need to capture and queue these changes. The benefit of queuing these changes is that we can decouple the process of maintaining the index from the request that updates the database. 
<p>The process of sending the entity to the queue consists of getting the information for each property’s custom attribute and value. The following code shows the implementation of this process. Full code here.&nbsp; <div id="codeSnippetWrapper">
<div id="codeSnippetWrapper"><pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; border-left-style: none; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> IndexQueueManager<br>{<br>...<br><br><span style="color: #0000ff">public</span> TData EnqueueEntity&lt;TData&gt;(Task&lt;TData&gt; tEntity, <span style="color: #0000ff">string</span> action) <span style="color: #0000ff">where</span> TData : <span style="color: #0000ff">class</span>, ITableData<br>    {<br><br>        <span style="color: #0000ff">if</span> (tEntity.IsFaulted)<br>        {<br>            <span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> InvalidOperationException(<span style="color: #006080">"Task in faulted state"</span>, tEntity.Exception);<br>        }<br>        <br>        var ixEntity = GetEntityIndexInfo&lt;TData&gt;(tEntity.Result, action);<br>        <br>        var msg = <span style="color: #0000ff">new</span> BrokeredMessage(JsonConvert.SerializeObject(ixEntity));<br>        msg.TimeToLive = <span style="color: #0000ff">new</span> TimeSpan(7, 0, 0, 0);<br>        _indexerQ.Send(msg);<br><br>        <span style="color: #0000ff">return</span> tEntity.Result;<br>    }<br>...  <br>}</pre><br></div><br></div>
<blockquote>
<p><font size="2">Note: The object that goes into the queue is an instance of EntityIndexInfo. You can find the source code <a href="https://github.com/giventocode/azure-mobileservices-search/blob/master/Giventocode.MobileServices.AzureSearch/IndexableEntityProperty.cs" target="_blank">here</a>.</font></p></blockquote>
<p>For the queue’s implementation, we will use the queuing capabilities of the Azure Service Bus. Service Bus provides orderly delivery of the messages, which is an important consideration because we need to guarantee updates to the index in the same order that changes to an entity occur. The following code shows the constructor of the IndexQueueManager class where we initialize the queue client. 
<div id="codeSnippetWrapper"><pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; border-left-style: none; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span style="color: #0000ff">public</span> IndexQueueManager(<span style="color: #0000ff">string</span> connString)<br>{<br>    <span style="color: #0000ff">if</span> (connString == <span style="color: #0000ff">null</span>)<br>    {<br>        <span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> ArgumentNullException(<span style="color: #006080">"connString"</span>);<br>    }            <br><br>    var mgr = NamespaceManager.CreateFromConnectionString(connString);<br><br>    <span style="color: #0000ff">if</span> (!mgr.QueueExists(<span style="color: #006080">"amsindexerqueue"</span>))<br>    {                <br>        var q = mgr.CreateQueue(<span style="color: #006080">"amsindexerqueue"</span>);              <br>    }<br><br>    _indexerQ = QueueClient.CreateFromConnectionString(connString,<span style="color: #006080">"amsindexerqueue"</span>);<br>    <br>}<br></pre><br></div>
<p>Finally, one elegant way to capture when these changes occurred is by overriding the insert, replace, update, and delete methods of the EntityDomainManager. The following code shows the implementation of a derived domain manager that, after performing a database operation, sends the entity to the queue. 
<p>&nbsp; <div id="codeSnippetWrapper"><pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; border-left-style: none; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> IndexableEntityDomainManager&lt;TData&gt; : EntityDomainManager&lt;TData&gt; <span style="color: #0000ff">where</span> TData : <span style="color: #0000ff">class</span>, ITableData, <span style="color: #0000ff">new</span>()<br>{<br>    <span style="color: #0000ff">private</span> IndexQueueManager IndexManager;<br><br>    <span style="color: #0000ff">public</span> IndexableEntityDomainManager(DbContext context, HttpRequestMessage request, ApiServices services, <span style="color: #0000ff">string</span> ServiceBusConnString)<br>        : <span style="color: #0000ff">base</span>(context, request, services)<br>    {<br>        <span style="color: #0000ff">if</span> (ServiceBusConnString == <span style="color: #0000ff">null</span>)<br>        {<br>            <span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> ArgumentNullException(<span style="color: #006080">"ServiceBusConnString"</span>);<br>        }<br><br>        <span style="color: #0000ff">this</span>.IndexManager = <span style="color: #0000ff">new</span> IndexQueueManager(ServiceBusConnString);<br>    }<br>    <span style="color: #0000ff">public</span>  <span style="color: #0000ff">override</span> Task&lt;TData&gt; ReplaceAsync(<span style="color: #0000ff">string</span> id, TData data)<br>    {<br>        <span style="color: #0000ff">return</span> <span style="color: #0000ff">base</span>.ReplaceAsync(id, data)<br>            .ContinueWith&lt;TData&gt;((t) =&gt; IndexManager.EnqueueEntity&lt;TData&gt;(t, <span style="color: #006080">"mergeOrUpload"</span>));            <br>    }<br><br>    <span style="color: #0000ff">public</span>  <span style="color: #0000ff">override</span> Task&lt;TData&gt; UpdateAsync(<span style="color: #0000ff">string</span> id, Delta&lt;TData&gt; patch)<br>    {<br>        <span style="color: #0000ff">return</span>  <span style="color: #0000ff">base</span>.UpdateAsync(id, patch)<br>                .ContinueWith&lt;TData&gt;((t) =&gt; IndexManager.EnqueueEntity&lt;TData&gt;(t, <span style="color: #006080">"merge"</span>)); ;<br>    }<br><br>    <span style="color: #0000ff">public</span>  <span style="color: #0000ff">override</span> Task&lt;TData&gt; InsertAsync(TData data)<br>    {<br>        <span style="color: #0000ff">return</span> <span style="color: #0000ff">base</span>.InsertAsync(data)<br>                    .ContinueWith&lt;TData&gt;((t) =&gt;IndexManager.EnqueueEntity&lt;TData&gt;(t, <span style="color: #006080">"upload"</span>));            <br>    }<br><br>    <span style="color: #0000ff">public</span>  <span style="color: #0000ff">override</span> Task&lt;<span style="color: #0000ff">bool</span>&gt; DeleteAsync(<span style="color: #0000ff">string</span> id)<br>    {<br>        <span style="color: #0000ff">return</span> <span style="color: #0000ff">base</span>.DeleteAsync(id)<br>            .ContinueWith&lt;<span style="color: #0000ff">bool</span>&gt;((t) =&gt; <br>                {<br>                    IndexManager.EnqueueEntity&lt;TData&gt;(Task&lt;TData&gt;.Run(() =&gt; <span style="color: #0000ff">new</span> TData() { Id = id }), <span style="color: #006080">"delete"</span>);<br>                    <span style="color: #0000ff">return</span> t.Result;<br>                });<br>        <br>    }<br>}</pre><br></div>
<h3>Maintaining the Index</h3>
<p>Now that we have the changes in the queue, we need to read the messages from the queue and update the index. The following code first reads a message and checks whether an index exists. If an index does not exist, the code creates one according to the definition included in the message. Finally, the code creates a document instance containing the changes to the entity and sends a request to update the index with this information. Check out the full implementation <a href="https://github.com/giventocode/azure-mobileservices-search/blob/master/Giventocode.MobileServices.AzureSearch/IndexQueueManager.cs" target="_blank">here</a>. 
<div id="codeSnippetWrapper">
<div id="codeSnippetWrapper"><pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; border-left-style: none; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> IndexQueueManager<br>{<br>...<br><br>    <span style="color: #0000ff">public</span> async Task&lt;Boolean&gt; ReadFromQueueAndIndexAsync()<br>    {<br>        <span style="color: #0000ff">try</span><br>        {<br>            var msg = _indexerQ.Receive();<br><br>            <span style="color: #0000ff">if</span> (msg == <span style="color: #0000ff">null</span>)<br>            {<br>                <span style="color: #0000ff">return</span> <span style="color: #0000ff">false</span>;<br>            }<br><br>            var indexInfo =  JsonConvert.DeserializeObject&lt;EntityIndexInfo&gt;(msg.GetBody&lt;<span style="color: #0000ff">string</span>&gt;());<br><br>            await CreateIndexIfNotExistsAsync(indexInfo);<br><br>            var indexDoc = GetIndexDocument(indexInfo);<br>            <br>            await IndexDocumentAsync(indexDoc);<br><br>            _indexerQ.Complete(msg.LockToken);<br><br>            <span style="color: #0000ff">return</span> <span style="color: #0000ff">true</span>;<br>        }<br>        <span style="color: #0000ff">catch</span>(Exception ex)<br>        {<br>            _indexerQ.Abort();<br><br>            <span style="color: #0000ff">throw</span> ex;<br>        }<br><br>    }<br>...<br>}</pre><br></div><br></div>
<p>After we wrap up this code as a scheduled job, we are ready to enable this functionality in our back-end! 
<div id="codeSnippetWrapper"><pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; border-left-style: none; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> IndexerJob : ScheduledJob<br>    {<br>        <span style="color: #0000ff">public</span> async <span style="color: #0000ff">override</span> Task ExecuteAsync()<br>        {<br>            var mgr = <span style="color: #0000ff">new</span> IndexQueueManager(CloudConfigurationManager.GetSetting(<span style="color: #006080">"Search_ServiceBusConnString"</span>));<br>            var maxNumberOfMgs = 1000;<br>            var processMsgs=0;<br><br>            <span style="color: #0000ff">while</span> (await mgr.ReadFromQueueAndIndexAsync() &amp;&amp; processMsgs &lt; maxNumberOfMgs)<br>            {<br>                processMsgs++;<br>                Services.Log.Info(<span style="color: #0000ff">string</span>.Format(<span style="color: #006080">"Processed message. Message count {0}"</span>,processMsgs.ToString()));<br>                <br>            }<br>                     <br>        }<br>    }</pre><br></div>
<h3>Using What We Built</h3>
<p>First things first: let’s create an Azure Search instance using the preview portal. 
<p>&nbsp;<a href="http://giventocode.com/Media/Default/Windows-Live-Writer/9113240f68e9_D273/CreateSearch_4.png"><img title="CreateSearch" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="CreateSearch" src="http://giventocode.com/Media/Default/Windows-Live-Writer/9113240f68e9_D273/CreateSearch_thumb_1.png" width="640" height="425"></a>
<p>&nbsp; <p>We are ready to use our custom attribute and domain manager. Let’s create a data model and decorate the properties using the custom attribute. 
<div id="codeSnippetWrapper">
<div id="codeSnippetWrapper"><pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; border-left-style: none; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><br><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> RockBand:EntityData<br>{<br>    [Indexable(<span style="color: #006080">"Edm.String"</span>, <span style="color: #0000ff">true</span>, Suggestions = <span style="color: #0000ff">true</span>, Retrievable = <span style="color: #0000ff">true</span>, Facetable = <span style="color: #0000ff">false</span>)]<br>    <span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> Name { get; set; }<br><br>    [Indexable(<span style="color: #006080">"Edm.String"</span>, <span style="color: #0000ff">true</span>,Facetable=<span style="color: #0000ff">false</span>)]<br>    <span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> Description { get; set; }<br><br>    [Indexable(<span style="color: #006080">"Edm.String"</span>, <span style="color: #0000ff">true</span>)]<br>    <span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> Genre { get; set; }<br>}</pre><br></div><br></div>
<p>Next, let’s create a table controller for the model that uses our domain manager. 
<div id="codeSnippetWrapper"><pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; border-left-style: none; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> RockBandController : TableController&lt;RockBand&gt;<br>{<br>  <span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> Initialize(HttpControllerContext controllerContext)<br>  {<br>      <span style="color: #0000ff">base</span>.Initialize(controllerContext);<br>      MobileServiceContext context = <span style="color: #0000ff">new</span> MobileServiceContext();<br>      DomainManager = <span style="color: #0000ff">new</span> IndexableEntityDomainManager&lt;RockBand&gt;(context, Request, Services, CloudConfigurationManager.GetSetting(<span style="color: #006080">"Search_ServiceBusConnString"</span>));<br>  }<br><br>  <span style="color: #008000">// GET tables/RockBand</span><br>  <span style="color: #0000ff">public</span> IQueryable&lt;RockBand&gt; GetAllRockBand()<br>  {<br>      <span style="color: #0000ff">return</span> Query(); <br>  }<br><br>  <span style="color: #008000">// GET tables/RockBand/48D68C86-6EA6-4C25-AA33-223FC9A27959</span><br>  <span style="color: #0000ff">public</span> SingleResult&lt;RockBand&gt; GetRockBand(<span style="color: #0000ff">string</span> id)<br>  {<br>      <span style="color: #0000ff">return</span> Lookup(id);<br>  }<br><br>  <span style="color: #008000">// PATCH tables/RockBand/48D68C86-6EA6-4C25-AA33-223FC9A27959</span><br>  <span style="color: #0000ff">public</span> Task&lt;RockBand&gt; PatchRockBand(<span style="color: #0000ff">string</span> id, Delta&lt;RockBand&gt; patch)<br>  {<br>       <span style="color: #0000ff">return</span> UpdateAsync(id, patch);<br>  }<br><br>  <span style="color: #008000">// POST tables/RockBand/48D68C86-6EA6-4C25-AA33-223FC9A27959</span><br>  <span style="color: #0000ff">public</span> async Task&lt;IHttpActionResult&gt; PostRockBand(RockBand item)<br>  {<br>      RockBand current = await InsertAsync(item);<br>      <span style="color: #0000ff">return</span> CreatedAtRoute(<span style="color: #006080">"Tables"</span>, <span style="color: #0000ff">new</span> { id = current.Id }, current);<br>  }<br><br>  <span style="color: #008000">// DELETE tables/RockBand/48D68C86-6EA6-4C25-AA33-223FC9A27959</span><br>  <span style="color: #0000ff">public</span> Task DeleteRockBand(<span style="color: #0000ff">string</span> id)<br>  {<br>       <span style="color: #0000ff">return</span> DeleteAsync(id);<br>  }<br><br>}</pre><br></div>
<p>Now we can insert a record, run the indexer job and check the index’s schema via the portal. 
<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/9113240f68e9_D273/image_2.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/9113240f68e9_D273/image_thumb.png" width="240" height="235"></a>&nbsp;<a href="http://giventocode.com/Media/Default/Windows-Live-Writer/9113240f68e9_D273/image_4.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/9113240f68e9_D273/image_thumb_1.png" width="240" height="166"></a></p>
<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/9113240f68e9_D273/image_6.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/9113240f68e9_D273/image_thumb_2.png" width="640" height="331"></a></p>
<p>&nbsp;</p>
<p>Finally, we can perform a search using a client app and view our results! 
<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/9113240f68e9_D273/image_10.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/9113240f68e9_D273/image_thumb_4.png" width="640" height="322"></a>
<p>You can find the source code for the whole solution <a href="https://github.com/giventocode/azure-mobileservices-search" target="_blank">here</a>. 












]]></content:encoded>
    </item>
    <item>
      <title>How to: Use Azure DocumentDB with Azure Mobile Services</title>
      <link>https://docs.microsoft.com/archive/blogs/giventocode/how-to-use-azure-documentdb-with-azure-mobile-services</link>
      <pubDate>Thu, 16 Oct 2014 15:24:22 GMT</pubDate>
      <dc:creator><![CDATA[giventocode]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/giventocode/2014/10/16/how-to-use-azure-documentdb-with-azure-mobile-services/</guid>
      <description><![CDATA[With the release of DocumentDB, developers now have access to a scalable, nimble, and robust NoSQL...]]></description>
      <content:encoded><![CDATA[<p>With the release of DocumentDB, developers now have access to a scalable, nimble, and robust NoSQL platform as a service in Azure. I thought it would be a good idea to showcase how you can use DocumentDB with Azure Mobile Services. But before we dive into the details, and with the goal of providing some insights into how I implemented this integration, let’s discuss some aspects of the design of Azure Mobile Services with a .NET back end.</p> <p>&nbsp;</p> <div style="font-size: 11px; max-width: 413px; font-family: 'Helvetica Neue',arial,sans-serif; width: 100%; color: #a7a7a7; display: inline-block; background-color: #fff"> <div style="overflow: hidden; height: 0px; width: 100%; position: relative; padding-bottom: 0px; padding-top: 100.24%; padding-left: 0px; padding-right: 0px"><iframe style="height: 100%; width: 100%; position: absolute; left: 0px; display: inline-block; top: 0px" height="414" src="http://blogs.msdn.com//embed.gettyimages.com/embed/168580476?et=w1kk1z4DQb5KhOnI3SKEwQ&amp;sig=pZHeSMXBPuhP-xNrI6N6N6WnVkSPNkIWPpksVudYmyQ=" frameborder="0" width="413" scrolling="no"></iframe></div> <p style="margin: 0px"></p> <div style="padding-bottom: 0px; text-align: left; padding-top: 0px; padding-left: 0px; margin: 0px 0px 0px 10px; padding-right: 0px"><a style="text-decoration: none; border-top: medium none; border-right: medium none; border-bottom: medium none; font-weight: normal !important; color: #a7a7a7; border-left: medium none; display: inline-block" href="http://www.gettyimages.com/detail/168580476" target="_blank">#168580476</a> / <a style="text-decoration: none; border-top: medium none; border-right: medium none; border-bottom: medium none; font-weight: normal !important; color: #a7a7a7; border-left: medium none; display: inline-block" href="http://www.gettyimages.com" target="_blank">gettyimages.com</a></div> <div style="padding-bottom: 0px; text-align: left; padding-top: 0px; padding-left: 0px; margin: 0px 0px 0px 10px; padding-right: 0px">&nbsp;</div></div> <blockquote> <p><font size="2"><strong>Note: </strong>This integration could be beneficial if you want to use some features of Azure Mobile Services, such as authentication, notifications, etc., while benefiting from a NoSQL database approach.<br></font></p></blockquote> <p>To get started, let’s cover some of the basics of Azure Mobile Services. First, it is important to notice that Azure Mobile Services with a .NET back end is built using the WebAPI, so controllers, models, routes, etc., are also the building blocks of the service. Another design consideration is that Azure Mobile Services separates the operations of the API and the mechanism that handles how the data is stored. Because of this separation of concerns, you can change where data comes from or where it is saved, without major changes to the implementation of the APIs. To achieve this, the design of Azure Mobile Services introduces the concept of a domain manager. </p> <p>The role of the domain manager is to manage the semantics of the underlying repository of data and provide a consistent interface that allows the typical create, read, update, and delete (CRUD) scenarios.&nbsp; On top of the domain manager, Azure Mobile Services provides a generic controller that exposes this functionality as REST operations. The controller also has a type parameter and is the type of entity representing the data that the client receives and sends to the API. This entity is often referred as a data transfer object (DTO). In the simplest case, the DTO reflects the underlying data model. </p> <p>&nbsp;</p> <p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/How-to-Use-Azure-DocumentDB_AA9B/image_11.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/How-to-Use-Azure-DocumentDB_AA9B/image_thumb_2.png" width="240" height="212"></a><br></p> <blockquote> <p><font size="2"><strong>Note:</strong> There are scenarios in which you will want to use an existing database where it is necessary to expose a subset or a variation of data via the API. In such cases, there is another set of objects that represents the data model, and creating a DTO mapping process of some sort is necessary. The implementation of Azure Mobile Services includes a convenient mapper component (Automap), as well as a mapping domain manager to facilitate these tasks.</font></p></blockquote> <p>Now let’s discuss DocumentDB. Simply put, you can think of DocumentDB as a JSON repository where each element (resource) is addressable via a URI. At the top is your account followed by a set of databases. Each database can have one or more collections of documents. A document is a main data unit, and in the context of Azure Mobile Services, entities are documents. To reflect this I will use the term “document entity” going forward.</p> <p>&nbsp;</p> <blockquote> <p><font size="2"><strong>Note:</strong> You can create a new DocumentDB service instance through the <a href="http://portal.azure.com/" target="_blank">preview portal</a> only.</font><font size="2"></p></blockquote></font> <p>&nbsp;</p> <p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/How-to-Use-Azure-DocumentDB_AA9B/image_14.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/How-to-Use-Azure-DocumentDB_AA9B/image_thumb_5.png" width="640" height="400"></a><br></p> <p>Following the design considerations discussed, we will create a domain manager that abstracts the nuances of persisting and retrieving documents from the DocumentDB instance and a controller that leverages it. So let’s get to it!</p> <h3>Document Domain Manager </h3> <p>For the implementation of the domain manager for DocumentDB, we will implement the methods shown in the diagram below, and to do this we will leverage the DocumentDB .NET SDK.</p> <p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/How-to-Use-Azure-DocumentDB_AA9B/image_23.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/How-to-Use-Azure-DocumentDB_AA9B/image_thumb_8.png" width="640" height="359"></a><br></p> <p>The methods are basically the same as those used for the interface IDomainManager&lt;T&gt;. Notice that we are not explicitly implementing this interface due to the constraint that makes instances of &lt;T&gt; implement the ITableData interface. ITableData defines basic properties that are not applicable for a document stored in DocumentDB. <br></p> <p>You can check the full implementation <a href="http://snipplr.com/view/79883/document-entity-domain-manager/">here</a>.</p> <p>&nbsp;</p> <blockquote> <p><font size="2"><strong>Note:</strong> This full implementation assumes that you have two settings in your config file: <strong>endpoint</strong> and <strong>authKey</strong>. You can get the values for these settings in the Azure portal. </font></p></blockquote> <h3>The Controller</h3><br> <p>Next, we will need to implement a base (abstract) controller that expects the domain manager we just discussed. In addition, we need to define a base type for our document entities. The DocumentDB client has a handy class called Resource, which has some basic properties that reflect key metadata of a document entity as well as an ID property. So let’s require that all document entities derive from this class by placing a constraint in our controller. </p> <p><br>The following figure shows the constraint and the methods we will need to implement. You can check the complete implementation <a href="http://snipplr.com/view/79884/documentdb-controller/">here</a>.<br></p> <p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/How-to-Use-Azure-DocumentDB_AA9B/image_20.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/How-to-Use-Azure-DocumentDB_AA9B/image_thumb_7.png" width="640" height="283"></a></p> <h3>Playing with DocumentDB</h3> <p>So now we have everything we need to define a new entity and then easily implement an API that exposes the CRUD operations having DocumentDB as the back end.<br>Let’s create a Todo item entity.</p> <p id="codeSnippetWrapper"><pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; border-left-style: none; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> DocumentTodoItem:Resource<br>    {<br><br>        [JsonProperty(PropertyName = <span style="color: #006080">"name"</span>)]<br>        <span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> Name { get; set; }<br><br>        [JsonProperty(PropertyName = <span style="color: #006080">"desc"</span>)]<br>        <span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> Description { get; set; }<br><br>        [JsonProperty(PropertyName = <span style="color: #006080">"isComplete"</span>)]<br>        <span style="color: #0000ff">public</span> <span style="color: #0000ff">bool</span> Completed { get; set; }<br>    }</pre><br><br>And a controller derived from our base controller class.</p>
<p>&nbsp;</p>
<p id="codeSnippetWrapper"><pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; border-left-style: none; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> TodoItemDocumentController:DocumentController&lt;DocumentTodoItem&gt;<br>    {<br>        <span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> Initialize(HttpControllerContext controllerContext)<br>        {<br>            <span style="color: #0000ff">base</span>.Initialize(controllerContext);<br>            DomainManager = <span style="color: #0000ff">new</span> DocumentEntityDomainManager&lt;DocumentTodoItem&gt;(<span style="color: #006080">"AMSDocumentDB"</span>, <span style="color: #006080">"todolist"</span>, Request, Services);<br>        }<br><br>        <span style="color: #0000ff">public</span> IQueryable&lt;DocumentTodoItem&gt; GetAllTodoItems()<br>        {<br>            <span style="color: #0000ff">return</span> Query();<br>        }<br><br>        <span style="color: #0000ff">public</span> SingleResult&lt;DocumentTodoItem&gt; GetTodoItem(<span style="color: #0000ff">string</span> id)<br>        {<br>            <span style="color: #0000ff">return</span> Lookup(id);<br>        }<br><br>        <span style="color: #0000ff">public</span> Task&lt;DocumentTodoItem&gt; ReplaceTodoItem(<span style="color: #0000ff">string</span> id, DocumentTodoItem item)<br>        {<br>            <span style="color: #0000ff">return</span> ReplaceAsync(id, item);<br>        }<br><br>        <span style="color: #0000ff">public</span> async Task&lt;IHttpActionResult&gt; PostTodoItem(DocumentTodoItem item)<br>        {<br>            var doc = await InsertAsync(item);     <br>            <br>            <span style="color: #0000ff">return</span> CreatedAtRoute(<span style="color: #006080">"DefaultApis"</span>, <span style="color: #0000ff">new</span> { id = doc.Id }, doc);<br>        }<br><br>        <span style="color: #0000ff">public</span> Task DeleteTodoItem(<span style="color: #0000ff">string</span> id)<br>        {<br>            <span style="color: #0000ff">return</span> DeleteAsync(id);<br>        }<br>    }</pre><br></p>
<p><br>Let’s run it locally and create a Todo item.</p>
<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/How-to-Use-Azure-DocumentDB_AA9B/image_25.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/How-to-Use-Azure-DocumentDB_AA9B/image_thumb_9.png" width="640" height="412"></a></p>
<p><br>Let’s check DocumentDB using Document Explorer via the portal—and voila!</p>
<p><br><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/How-to-Use-Azure-DocumentDB_AA9B/image_27.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/How-to-Use-Azure-DocumentDB_AA9B/image_thumb_10.png" width="640" height="354"></a></p>
<h3>&nbsp;</h3>
<h3>Conclusion</h3>
<p><br>In today’s blog post, I showed you how you can use DocumentDB as the back end for Azure Mobile Services. You can find the complete example here.</p>]]></content:encoded>
    </item>
    <item>
      <title>Build a Recommendations System for your Blog or Web Site using Azure Machine Learning and Azure Mobile Services</title>
      <link>https://docs.microsoft.com/archive/blogs/giventocode/build-a-recommendations-system-for-your-blog-or-web-site-using-azure-machine-learning-and-azure-mobile-services</link>
      <pubDate>Wed, 10 Sep 2014 22:00:57 GMT</pubDate>
      <dc:creator><![CDATA[giventocode]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/giventocode/2014/09/10/build-a-recommendations-system-for-your-blog-or-web-site-using-azure-machine-learning-and-azure-mobile-services/</guid>
      <description><![CDATA[#184102522 / gettyimages.com &nbsp; Maybe you have noticed the panel with a post’s...]]></description>
      <content:encoded><![CDATA[<div style="font-size: 11px; max-width: 507px; font-family: 'Helvetica Neue',arial,sans-serif; width: 100%; min-width: 300px; color: #a7a7a7; display: inline-block; background-color: #fff"> <div style="overflow: hidden; height: 0px; width: 100%; position: relative; padding-bottom: 0px; padding-top: 66.66%; padding-left: 0px; padding-right: 0px"><iframe style="height: 100%; width: 100%; position: absolute; left: 0px; display: inline-block; top: 0px" height="338" src="http://blogs.msdn.com//embed.gettyimages.com/embed/184102522?et=0idS4Zo8R_FO5IfVWZII0Q&amp;sig=6fjHDnH6Ab3xODR7glHzM93y9dxAdYPjaQVUFIlWtV0=" frameborder="0" width="507" scrolling="no"></iframe></div> <p style="margin: 0px"></p> <div style="padding-bottom: 0px; text-align: left; padding-top: 0px; padding-left: 0px; margin: 0px 0px 0px 10px; padding-right: 0px"><a style="text-decoration: none; border-top: medium none; border-right: medium none; border-bottom: medium none; font-weight: normal !important; color: #a7a7a7; border-left: medium none; display: inline-block" href="http://www.gettyimages.com/detail/184102522" target="_blank">#184102522</a> / <a style="text-decoration: none; border-top: medium none; border-right: medium none; border-bottom: medium none; font-weight: normal !important; color: #a7a7a7; border-left: medium none; display: inline-block" href="http://www.gettyimages.com" target="_blank">gettyimages.com</a></div></div> <p>&nbsp;</p> <p>Maybe you have noticed the panel with a post’s recommendations next to the blog post itself and wondered how it works.<br></p> <p>In today’s post I’ll describe the implementation of this feature, which leverages some really cool Azure technology including Azure Machine Learning (Azure ML), Azure Mobile Services and Azure Storage. </p> <p><br>But first, let me give you a quick overview of the approach to developing this recommendations mechanism and the rationale behind it. The goal is simply to provide a set of recommendations of similar content directly from a blog post. One way to achieve this goal is to treat this as a categorization problem. Once all of the blog posts have a category assigned to them, the solution provides recommendations from the categories that the blog posts share. </p> <p><br>If we go down this path, first we would define these categories and create a set of data (a training dataset) categorized according to our expectations. From this data, we would train a machine learning model for future categorization. In my case, this means that I’d need to categorize some of my data manually and select and train a model. Once the model is trained, I could use it to categorize the rest of the data automatically. If we were dealing with tens of thousands of articles or blog posts, the effort would be justifiable. However, for my blog that has significantly less content, I might just spend time tagging my content and doing the categorization myself. <br>&nbsp;</p> <blockquote> <p><font size="2"><strong>Note:</strong> In the context of machine learning, the above-described approach is known as <em><strong>supervised learning</strong></em>.&nbsp; </font>&nbsp;</p></blockquote> <p><br>Now, say we could categorize the data without having to provide a training data set or the categories up front. The only decision we would make would be the number of groups of data. The similarity of the text would define what would go into each group. <br></p> <p>This approach would be analogous to giving a person several blog posts and a number of bins and tasking the person with placing blog posts in bins corresponding to their degree of similarity. As such, each bin would contain a group of the most similar blog posts. </p> <p>&nbsp;</p> <div style="font-size: 11px; max-width: 507px; font-family: 'Helvetica Neue',arial,sans-serif; width: 100%; min-width: 300px; color: #a7a7a7; display: inline-block; background-color: #fff"> <div style="overflow: hidden; height: 0px; width: 100%; position: relative; padding-bottom: 0px; padding-top: 66.66%; padding-left: 0px; padding-right: 0px"><iframe style="height: 100%; width: 100%; position: absolute; left: 0px; display: inline-block; top: 0px" height="338" src="http://blogs.msdn.com//embed.gettyimages.com/embed/176642756?et=rOOI5fyORlBNN_RZgVJ6kg&amp;sig=fglFZHpzvEocyURZjt0ZyK-2w5TFwwk835cl97QNIuU=" frameborder="0" width="507" scrolling="no"></iframe></div> <p style="margin: 0px"></p> <div style="padding-bottom: 0px; text-align: left; padding-top: 0px; padding-left: 0px; margin: 0px 0px 0px 10px; padding-right: 0px"><a style="text-decoration: none; border-top: medium none; border-right: medium none; border-bottom: medium none; font-weight: normal !important; color: #a7a7a7; border-left: medium none; display: inline-block" href="http://www.gettyimages.com/detail/176642756" target="_blank">#176642756</a> / <a style="text-decoration: none; border-top: medium none; border-right: medium none; border-bottom: medium none; font-weight: normal !important; color: #a7a7a7; border-left: medium none; display: inline-block" href="http://www.gettyimages.com" target="_blank">gettyimages.com</a></div></div> <p><br>&nbsp;</p> <p>One algorithm that performs this type of analysis is K-Means clustering. K represents the number of centroids (centers of the clusters) that the algorithm will try to find in the data. In my scenario, you can think of the centroids as the bins or groups of data. This is the approach I used, so let’s get to it!</p> <p>&nbsp;</p> <blockquote> <p><font size="2"><strong>Note:</strong> One of the trade-offs with K-Means clustering is that there is not a deterministic way to know the optimal value of K. This is what is known as a <a href="http://en.wikipedia.org/wiki/NP-hard">NP-hard</a> problem. </font><font size="2">Clustering is an example of <strong><em>unsupervised learning</em></strong>.</font></p></blockquote> <p>&nbsp;</p> <h3>Data In</h3> <p>To get my blog’s data ready for K-Means using Azure ML, there are a few preparatory steps, including removing HTML, CSS, and the stop words.&nbsp; </p> <p>&nbsp;</p> <blockquote> <p><font size="2"><strong>Note:</strong> “Stop words” are repeating words that are often removed from machine learning analysis due to their high frequency and limited semantic value. For example “the”.</font></p></blockquote> <p>&nbsp;</p> <p>Once the data is ready, I have to present it in a format that Azure ML can read. To implement all of these tasks, I leverage the job-scheduling capabilities of Azure Mobile Services.<br></p> <p>The code shows, the relevant part of the implementation of the scheduled job that reads the blog’s data from the RSS feed, cleans it, and persist it in an Azure table (you can get the full code here).</p> <div id="codeSnippetWrapper"><pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; border-left-style: none; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><br>    <span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> RssMLPrep : ScheduledJob<br>    {<br><br>        <span style="color: #0000ff">public</span> async <span style="color: #0000ff">override</span> Task ExecuteAsync()<br>        {<br><br>            <span style="color: #0000ff">using</span> (var httpClient = <span style="color: #0000ff">new</span> HttpClient())<br>            {<br><br>                var response = await httpClient.GetAsync(<span style="color: #0000ff">new</span> Uri(CloudConfigurationManager.GetSetting(<span style="color: #006080">"RssSource"</span>)));<br>                var data = await response.Content.ReadAsStringAsync();<br>                var xnodes = <span style="color: #0000ff">new</span> XPathDocument(<span style="color: #0000ff">new</span> MemoryStream(UTF8Encoding.UTF8.GetBytes(data)))<br>                              .CreateNavigator()<br>                              .Select(<span style="color: #006080">"//item"</span>);<br><br>                var table = GetCloudTable();<br><br><br>                <span style="color: #0000ff">foreach</span> (XPathNavigator node <span style="color: #0000ff">in</span> xnodes)<br>                {<br>                    var title = node.SelectSingleNode(<span style="color: #006080">"title"</span>).ToString();<br><br>                    <span style="color: #008000">//Include the title in the text and prepare text...</span><br>                    var text = PrepareText(<span style="color: #0000ff">string</span>.Format(<span style="color: #006080">"{0} {1}"</span>, title, node.SelectSingleNode(<span style="color: #006080">"description"</span>).ToString()));<br><br>                    <span style="color: #008000">//hash the title to remove invalid chars and use it as the key</span><br>                    var rowKey = ComputeSH1Hash(title);<br>                    <br>                    var tableOp = TableOperation.InsertOrMerge(<span style="color: #0000ff">new</span> BlogEntry()<br>                    {<br>                        Text = text,<br>                        PubDate = DateTime.Now,<br>                        Link = node.SelectSingleNode(<span style="color: #006080">"link"</span>).ToString(),<br>                        RowKey = rowKey,<br>                        PartitionKey = <span style="color: #006080">"BlogEntries"</span>,<br>                        Title = title<br>                    });<br><br>                    await table.ExecuteAsync(tableOp);<br><br>                }<br><br>            }         <br>        }<br>      ...<br>}</pre><br></div>
<div class="csharpcode-wrapper">&nbsp;</div>
<div class="csharpcode-wrapper">Keep in mind that before you can run the experiment, you will need to run the scheduled job at least once to populate the data. For more information about deployment and testing of Jobs in Azure Mobile Services, see <a href="http://azure.microsoft.com/en-us/documentation/articles/mobile-services-dotnet-backend-schedule-recurring-tasks/">here</a>.</div>
<div class="csharpcode-wrapper">&nbsp;</div>
<h3>The Experiment</h3>
<p>&nbsp;</p>
<p>Next, I will describe the implementation of the clustering process in Azure ML. </p>
<p><br><strong>1.- Connecting the Modules and Configuring the Reader<br></strong></p>
<p>&nbsp;</p>
<p>First, we sign into Azure ML Studio and create a new experiment. From the list of modules on the left pane, locate and drop into the experiment the following modules: <strong>Reader</strong>, <strong>K-Means Clustering</strong>, <strong>Train Clustering Model</strong>, <strong>Feature Hashing</strong>, <strong>Execute R Script, Metadata Editor </strong>and <strong>Writer</strong> modules. Connect the modules according to the screenshot below.</p>
<p>&nbsp;</p>
<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/ecf99c5df1c3_11B6D/image_24.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/ecf99c5df1c3_11B6D/image_thumb_11.png" width="640" height="473"></a></p>
<p><br>Click on the Reader module and configure the properties so that it can read from the Azure table.</p>
<p>&nbsp;</p>
<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/ecf99c5df1c3_11B6D/image_34.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/ecf99c5df1c3_11B6D/image_thumb_16.png" width="406" height="447"></a></p>
<p>&nbsp;</p>
<p><strong>2.- Feature Hashing and Principal Component Analysis (PCA)<br></strong></p>
<p>&nbsp;</p>
<p>Next, we need to convert the blog’s text data into a format that K-Means can use. K-Means assumes a vector of n-dimensions as the input. Furthermore, since K-Means utilizes a Euclidian distance calculation to determine how close a vector is from the centroid, it is important that these dimensions contain numeric values and that these values are normalized. <br></p>
<p>&nbsp;</p>
<p>Although it sounds a bit complex, fortunately a technique called feature hashing simplifies the implementation of these tasks. Additionally, Azure ML provides a Feature Hashing module that leverages the Vowpal Wabbit library to perform a 32-bit murmurhash v3 hashing.<br></p>
<p>To use this module, we must indicate the column with the text we want to hash, the hashing bit size, and the length of the N-grams. The figure below shows you the properties of the module.</p>
<p>&nbsp;</p>
<blockquote>
<p><font size="2"><strong>Note:</strong> An N-grams value of 2 indicates that we will hash terms consisting of two words each.</font></p></blockquote>
<p>&nbsp;</p>
<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/ecf99c5df1c3_11B6D/image_32.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/ecf99c5df1c3_11B6D/image_thumb_15.png" width="406" height="286"></a></p>
<p>&nbsp;</p>
<p>The result of this module will be 4,096 new numeric columns for each row! This implies that K-Means will try to find K number of clusters in a space of 4,096 dimensions. This is a problem that is often referred to as the “curse of dimensionality” and specifically for K-Means is that the concept of distance becomes less precise as the number of dimensions grows.&nbsp; </p>
<p>&nbsp;</p>
<blockquote>
<p><font size="2"><strong>Note:</strong> Determining the number of columns is the hashing bit size parameter. Because we entered 12, this translates into 2^12 columns, which is 4,096.</font></p></blockquote>
<p><br>Another technique commonly used to reduce the number of dimensions is Principal Component Analysis (PCA). To do this in Azure ML, we will need to implement the following R code using the <strong>Execute R Script</strong> module.</p>
<p>&nbsp;</p>
<blockquote>
<p><font size="2"><strong>Note:</strong> The script selects the top 10 principal components. Depending on your data, however, you might find it beneficial to use this filter as a tuning parameter and return greater or fewer components</font></p></blockquote>
<div id="codeSnippetWrapper" class="csharpcode-wrapper">
<div id="codeSnippetWrapper" class="csharpcode-wrapper">
<div id="codeSnippetWrapper"><pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; border-left-style: none; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4">dataset1 &lt;- maml.mapInputPort(1) <span style="color: #008000"># class: data.frame</span><br><br><span style="color: #008000">#rowkey, title, link, pubdate, partitionkey, timestamp</span><br>reference_data &lt;- dataset1[,1:7]<br><br><span style="color: #008000">#pca on the hashed cols</span><br>pca_results &lt;- prcomp(dataset1[,8:4103])<br><br><span style="color: #008000">#take only the top 10 principal components</span><br>top_components &lt;- data.frame(pca_results$x[,1:10])<br><br><span style="color: #008000">#bind the results to the reference data</span><br>data.set &lt;- cbind(reference_data,top_components)<br><br>maml.mapOutputPort(<span style="color: #006080">"data.set"</span>);</pre><br></div>
<div>&nbsp;</div></div>
<div class="csharpcode"><strong>3.- K-Means and Model Training</strong></div>
<div class="csharpcode"><strong>&nbsp;</div></div></strong>
<p>At this point, we have the data ready for our model! As I mentioned earlier, there is no exact way to know the optimal value of K. However, one way to approach this is to think about the number of high-level topics or themes that your content covers. For my case, I thought that 5 would be a good starting point. The following image shows the configuration of the <strong>K-Means Model</strong> and <strong>Training Clustering Model</strong> modules.<br></p>
<p>&nbsp;</p>
<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/ecf99c5df1c3_11B6D/image_30.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/ecf99c5df1c3_11B6D/image_thumb_14.png" width="406" height="289"></a></p>
<p>&nbsp;</p>
<blockquote>
<p><font size="2"><strong>Note:</strong> The initialization in K-Means could be a key factor in the quality of the outcome. By default, the algorithm picks the top dimensions as the starting points for the centroids. However, a better initialization that is geared toward avoiding some of the shortcomings of the default approach is K-Means++, and Azure ML provides this initialization optimization!</font></p></blockquote>
<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/ecf99c5df1c3_11B6D/image_38.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/ecf99c5df1c3_11B6D/image_thumb_18.png" width="403" height="191"></a></p>
<p><strong>Important:</strong> When configuring the selected columns in <strong>Train Clustering Model</strong> module, make sure that you select the option <strong>Allow duplicates and preserve column order in selection.</strong></p>
<p><strong></strong>&nbsp;</p>
<p><strong>4.- Writing Our Results and Running the Experiment</strong><br></p>
<p>Before writing our results we need to convert the <strong>Assignments</strong> column to <strong>String</strong>. For this we will use the<strong> Metadata Editor </strong>module<strong> </strong>with the following properties.</p>
<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/ecf99c5df1c3_11B6D/image_26.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/ecf99c5df1c3_11B6D/image_thumb_12.png" width="403" height="395"></a></p>
<p>&nbsp;</p>
<p>Finally, we write our results in an Azure table using the <strong>Writer</strong> module. So let’s configure the <strong>Writer </strong>according to the figure below.</p>
<p><br><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/ecf99c5df1c3_11B6D/image_18.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/ecf99c5df1c3_11B6D/image_thumb_8.png" width="403" height="444"></a></p>
<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/ecf99c5df1c3_11B6D/image_20.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/ecf99c5df1c3_11B6D/image_thumb_9.png" width="403" height="322"></a></p>
<p><br>Ready, set, run the experiment by clicking on the <strong>Run</strong> button!</p>
<p>&nbsp;</p>
<h3>Data Out</h3>
<p><br>We are almost there! What is left is to expose the results table via Azure Mobile services and the client code. The following code shows the relevant part of the implementation via a custom API. (You can get the full code here.)</p>
<div id="codeSnippetWrapper"><pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; border-left-style: none; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> BlogRecommendationsController : ApiController<br>{<br>    <span style="color: #0000ff">public</span> ApiServices Services { get; set; }<br><br><br>    <span style="color: #008000">// GET api/BlogRecommendations</span><br>    [AuthorizeLevel(Microsoft.WindowsAzure.Mobile.Service.Security.AuthorizationLevel.Application)]<br>    <span style="color: #0000ff">public</span> IEnumerable&lt;BlogItem&gt; Get(<span style="color: #0000ff">string</span> title)<br>    {<br>        var resultsTable = GetCloudTable(<span style="color: #006080">"BlogDataTableResults"</span>);<br><br>        var cluster =resultsTable.CreateQuery&lt;BlogEntryResult&gt;()<br>                    .Where&lt;BlogEntryResult&gt;(b =&gt; b.Title == title)<br>                    .Select&lt;BlogEntryResult, <span style="color: #0000ff">string</span>&gt;<br>                    (r =&gt; r.Assignments)<br>                    .FirstOrDefault&lt;<span style="color: #0000ff">string</span>&gt;();<br><br>        <span style="color: #0000ff">if</span> (cluster != <span style="color: #0000ff">null</span>)<br>        {<br>            <span style="color: #0000ff">return</span> resultsTable.CreateQuery&lt;BlogEntryResult&gt;()<br>                    .Where&lt;BlogEntryResult&gt;(b =&gt; b.Assignments == cluster &amp;&amp; b.Title != title)<br>                    .Select&lt;BlogEntryResult, BlogItem&gt;<br>                    (r =&gt; <span style="color: #0000ff">new</span> BlogItem() { Title = r.Title, Link = r.Link });<br>        }<br><br>        <span style="color: #0000ff">return</span> <span style="color: #0000ff">null</span>;<br>    }<br>...<br>}</pre><br></div>
<p>For the client, I am using the Azure Mobile Services HTML SDK. The following code shows the implementation of the client code:</p>
<p>&nbsp;</p>
<div id="codeSnippetWrapper"><pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; border-left-style: none; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4">$(<span style="color: #006080">"#recommendation_panel"</span>).hide();<br><br><span style="color: #0000ff">var</span> client = <span style="color: #0000ff">new</span> WindowsAzure.MobileServiceClient(<br>    <span style="color: #006080">"https://&lt;YOUR MOBILE SERVICE&gt;.azure-mobile.net/"</span>,<br>    <span style="color: #006080">"&lt;YOUR_APP_KEY&gt;"</span><br>);<br><br><span style="color: #008000">//We are assuming the value in the HTML title tag is equal to the title of the RSS feed</span><br><span style="color: #0000ff">var</span> rawTitle = $(document).attr(<span style="color: #006080">'title'</span>);<br><br>client.invokeApi(<span style="color: #006080">"BlogRecommendations"</span>, {<br>        body: <span style="color: #0000ff">null</span>,<br>        parameters: {title:rawTitle},<br>        method: <span style="color: #006080">"get"</span><br>    }).done(<span style="color: #0000ff">function</span> (results) {      <br>        showRecommendations(results.result);        <br>    }, <span style="color: #0000ff">function</span>(error) {<br>        <span style="color: #008000">//error handling...</span><br>    });<br><br><span style="color: #0000ff">function</span> showRecommendations(items){    <br>    <span style="color: #0000ff">if</span>(items == <span style="color: #0000ff">null</span>){<br>        <span style="color: #0000ff">return</span>;<br>    }  <br><br>    <span style="color: #0000ff">if</span> (items.length &lt;= 0){<br>        <span style="color: #0000ff">return</span>;<br>    }<br><br><br>    $(<span style="color: #006080">"#recommendation_panel"</span>).show();<br>    <span style="color: #0000ff">var</span> lst = $(<span style="color: #006080">"#recommendation_body"</span>).append(<span style="color: #006080">'&lt;div class="list-group"/&gt;'</span>); <br>    <br>    items.forEach(<span style="color: #0000ff">function</span>(r,i,a) {<br>         lst.append(<span style="color: #006080">'&lt;a class="list-group-item" href="'</span> + r.link + <span style="color: #006080">'"&gt;'</span>+r.title+<span style="color: #006080">'&lt;/a&gt;'</span>);   <br>    })<br><br>    $(<span style="color: #006080">"#recommendation_header"</span>).append(<span style="color: #006080">"Recommended Posts"</span>); <br>    $(<span style="color: #006080">"#recommendation_footer"</span>).append(<span style="color: #006080">"Powered by Azure Machine Learning"</span>); <br>}</pre><br></div>
<p>&nbsp;</p>
<blockquote>
<p><font size="2"><strong>Note:</strong> You will need to configure CORS for the Azure Mobile Service. CORS is supported in Azure Mobile Services with a .NET backend starting version 1.0.348. For more information, see this <a href="http://azure.microsoft.com/blog/2014/07/28/azure-mobile-services-net-updates/">blog</a>.</font></p></blockquote>
<p>&nbsp;</p>
<h3>Final Thoughts!</h3><br>
<p>In today’s post, I showed you how to implement a recommendations feature for your blog or web site quickly by utilizing the K-Means clustering algorithm in Azure ML.</p>
<p>In future blog posts, I will show you some of the optimizations I did, given the results I got from the approach outlined here.&nbsp; </p>
<p>Stay tuned!</p>]]></content:encoded>
    </item>
    <item>
      <title>Regressions with Azure Machine Learning</title>
      <link>https://docs.microsoft.com/archive/blogs/giventocode/regressions-with-azure-machine-learning</link>
      <pubDate>Mon, 11 Aug 2014 18:17:00 GMT</pubDate>
      <dc:creator><![CDATA[giventocode]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/giventocode/2014/08/11/regressions-with-azure-machine-learning/</guid>
      <description><![CDATA[&nbsp; In today’s post, I’ll explore how you can use Azure Machine Learning to perform regression...]]></description>
      <content:encoded><![CDATA[<blockquote> <p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/Azure-Machine-Learning-Regressions_4A87/image_8.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/Azure-Machine-Learning-Regressions_4A87/image_thumb_3.png" width="640" height="470"></a></p></blockquote> <p>&nbsp;</p> <p>In today’s post, I’ll explore how you can use Azure Machine Learning to perform regression analysis on a dataset.</p> <p>Regression analysis is a data mining process that identifies a model that depicts the correlation between an outcome and one or more predictors. </p> <p>But, why is this important or useful?&nbsp; Well, for one thing,&nbsp; using a trained model,&nbsp; you could predict an outcome given a set of known values. In other words, you have the ability to gain insights into a likely outcome that is yet to happen.&nbsp; Interesting, right?</p> <p>&nbsp;</p> <h3>The Dataset</h3> <p>&nbsp;</p> <p>One very compelling source of data is the <a href="https://nycopendata.socrata.com/">NYC Open Data</a> portal. The portal features datasets containing a wide range of topics and categories related to New York City.&nbsp; Information about schools, restaurants ratings, pot holes, just to mention a few, is available via the portal. </p> <p>While browsing the data I came across the <a href="https://nycopendata.socrata.com/Social-Services/311-Service-Requests-from-2010-to-Present/erm2-nwe9?">311 Service Requests</a> dataset. This dataset contains all the <a href="http://www1.nyc.gov/311/">311</a> service requests from 2010 to present.&nbsp; If you are not familiar with 311, think of it as a customer service line for all the non-emergency requests to New York City’s government.&nbsp; So I decided to&nbsp; upload the dataset to Azure ML and use the visualization tools of Azure ML (Machine Learning) to find what’s the most frequent complaint of the very vocal New Yorkers.</p> <p>&nbsp;</p> <blockquote> <p><span style="font-size: small" size="2"><strong>Note:</strong>&nbsp; To upload a dataset in a CSV format you will need to create a ML workspace via the Azure Portal, sign-in into ML Studio and create a new Experiment. More information </span><a href="https://studio.azureml.net/Help/html/76fa12eb-54a6-4458-a20a-9f3186024358.htm"><span style="font-size: small" size="2">here</span></a><span style="font-size: small" size="2">.&nbsp; </span></p> <p><span style="font-size: small" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; For more information about how to visualize your data <a href="https://studio.azureml.net/Help/html/723a36c3-a229-446e-b917-a30763ed6944.htm">here</a>.</span></p></blockquote> <p>&nbsp;</p> <p>To my surprise, I learned that the most frequent complaints in 2013 were heating related.</p> <p>&nbsp;</p> <p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/Azure-Machine-Learning-Regressions_4A87/image_4.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/Azure-Machine-Learning-Regressions_4A87/image_thumb_1.png" width="440" height="480"></a></p> <p>&nbsp;</p> <h3>The Predictor</h3> <p>I thought it’d be interesting to create a model to predict the number of heating complaints.&nbsp; For the predictor of the number of heating complaints,&nbsp; I think you’d agree that there must be a correlation between the temperature and the number of these complaints.&nbsp; So next, I needed to find the average temperature of when the complaint was created.&nbsp; And fortunately, there’s a dataset for that! <a href="http://www.ncdc.noaa.gov/cdo-web/datasets">NOAA National Climatic Data Center</a>.</p> <p>After creating a database on Azure, importing the data and a bit of T-SQL’s aerobics. I ended up with a dataset containing two columns: the number of heating complaints and the average temperature of when they occurred. I added a Reader node (to read data from my Azure SQL table) to my experiment and removed the original dataset. I am ready to go.</p> <p>&nbsp;</p> <blockquote> <p><span style="font-size: small" size="2"><strong>Note: </strong>In Azure ML you have the ability to train your models from datasets that you upload, but also from SQL Azure, Table/Blob Storage, HTTP endpoints and other sources. For more information see </span><a href="https://studio.azureml.net/Help/?topic=html/4e1b0fe6-aded-4b3f-a36f-39b8862b9004.htm"><span style="font-size: small" size="2">this</span></a><span style="font-size: small" size="2">.</span></p></blockquote> <p>&nbsp;</p> <p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/Azure-Machine-Learning-Regressions_4A87/image_6.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/Azure-Machine-Learning-Regressions_4A87/image_thumb_2.png" width="455" height="480"></a></p> <p>&nbsp;</p> <h3>Linear Regression</h3> <p>Let’s start with the simplest the regression: lineal regression.&nbsp; In short, a linear model (identified from the process of regression) assumes that there’s a proportional relationship between to predictor (AvgDailyTemp)&nbsp; and the outcome (Complaints).&nbsp; So let’s train a Linear Model using Azure ML and our dataset. </p> <p>The modeling process in Azure ML, at a high level consists of finding the parameters of your model from your dataset (Train Model), test it with a dataset, which could be a different dataset to the one you use for training (Score Model)&nbsp; and then determine some&nbsp; key quality factors of the results or evaluate against another model (Evaluate Model).</p> <p>To do this, you need to drop a Train Model, Score Model, Evaluate Model and Linear Regression nodes into the experiment and connect them as depicted below.</p> <p>&nbsp;</p> <blockquote> <p><span style="font-size: small" size="2"><strong>Note:</strong> You could fine tune the linear regression process by changing the Solution Method (Ordinary Least Squares or Online Gradient Descent), whether to include an intercept and other parameters. For more information see <a href="https://studio.azureml.net/Help/?topic=html/31960a6f-789b-4cf7-88d6-2e1152c0bd1a.htm">here</a>.</span></p></blockquote> <p>&nbsp;</p> <p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/Azure-Machine-Learning-Regressions_4A87/image_15.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/Azure-Machine-Learning-Regressions_4A87/image_thumb_6.png" width="500" height="395"></a></p> <p>&nbsp;</p> <p>Next you need to configure the Train Model node to select the Complaints column –this how you tell Azure ML what is the predicted outcome of your model. </p> <p>&nbsp;</p> <p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/Azure-Machine-Learning-Regressions_4A87/image_12.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/Azure-Machine-Learning-Regressions_4A87/image_thumb_5.png" width="206" height="240"></a></p> <p>&nbsp;</p> <p>&nbsp;</p> <p>So let’s see how the model did.&nbsp; The following image shows Azure ML’s visualization of the predicted values next to the scattered plot of the actual values.</p> <p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/Azure-Machine-Learning-Regressions_4A87/image_17.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/Azure-Machine-Learning-Regressions_4A87/image_thumb_7.png" width="640" height="322"></a></p> <h3>&nbsp;</h3> <h3>Possion Regression and Log Scale</h3> <p>&nbsp;</p> <p>From the scatter plot of the actual values, you can tell that although the values are very scattered, the plot resembles an exponential function.&nbsp; However, having an exponential model means that we would loose the ease of regression of the linear model. Fortunately, we can have both. We do this by just transforming a component of our model, in our case the outcome, into the&nbsp; logarithm of number of complaints. And the transformation means that our model instead of predicting the number of complaints, will predict the log of the number of complaints.&nbsp; Let’s plot that scenario.</p> <p>&nbsp;</p> <p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/Azure-Machine-Learning-Regressions_4A87/image_19.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/Azure-Machine-Learning-Regressions_4A87/image_thumb_8.png" width="602" height="480"></a></p> <p>&nbsp;</p> <p>As you can see from the plot the trend is linear, once we do the transformation. So we can either go back to our data and apply the log function to the Complaints column or we can use the Possion regression. The outcome of the Possion regression is precisely the natural log of the outcome variable.&nbsp; Your experiment should look similar to the picture below.</p> <p>&nbsp;</p> <p>&nbsp;<a href="http://giventocode.com/Media/Default/Windows-Live-Writer/Azure-Machine-Learning-Regressions_4A87/image_21.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/Azure-Machine-Learning-Regressions_4A87/image_thumb_9.png" width="640" height="427"></a></p> <p>Now if we plot the scored model vs the actual data the get the following.</p> <p>&nbsp;</p> <p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/Azure-Machine-Learning-Regressions_4A87/image_23.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/Azure-Machine-Learning-Regressions_4A87/image_thumb_10.png" width="640" height="294"></a></p> <p>&nbsp;</p> <p>By looking at the graph it seems to reflect better the actual shape and scale of values.</p> <p>&nbsp;</p> <h3>Closing notes</h3> <p>&nbsp;</p> <p>In this blog post I showed you how to visualize data,&nbsp; create linear and Possion regressions using Azure ML.</p> <p>Next, I’ll show you&nbsp; how can use decision forests to get a model that better fits the data. </p>]]></content:encoded>
    </item>
    <item>
      <title>Geotag-Geopoint your Entities using Azure Mobile Services</title>
      <link>https://docs.microsoft.com/archive/blogs/giventocode/geotag-geopoint-your-entities-using-azure-mobile-services</link>
      <pubDate>Tue, 24 Jun 2014 22:54:00 GMT</pubDate>
      <dc:creator><![CDATA[giventocode]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/giventocode/2014/06/24/geotag-geopoint-your-entities-using-azure-mobile-services/</guid>
      <description><![CDATA[Associating your data with geo-location information could unlock powerful and highly useful...]]></description>
      <content:encoded><![CDATA[<p>Associating your data with geo-location information could unlock powerful and highly useful scenarios for your application.&nbsp; In this blog post, I will discus how you can associate, persist and use geo-location data with your entities.&nbsp; The usage scenario I will be covering is how you can retrieve entities closest to a geo-point.</p>
<p>But first, let&rsquo;s review a few key concepts about geo-locations and calculation of distances.</p>
<h3>News: The Earth isn&rsquo;t flat!</h3>
<p>If you think of the values of longitude and latitude as a Cartesian coordinate system (in 2 dimensions) calculating distances between two points is a simple calculation - thank you Pythagoras.</p>
<p>&nbsp;</p>
<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/Geotag-your-Entities-using-Azure-Mobile-_FFE5/image_2.png"><img width="300" height="238" title="image" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/Geotag-your-Entities-using-Azure-Mobile-_FFE5/image_thumb.png" border="0" /></a></p>
<p>But as early Greeks correctly deducted, the Earth&rsquo;s shape resembles a sphere &ndash;although not a perfect one, it&rsquo;s more of a flattened sphere. So if we use a trigonometric approach to&nbsp; calculate the distance between two points, we&rsquo;ll be off as the distance between two geo points is not a straight line but an arc segment on the Earth&rsquo;s curvature.&nbsp; In mathematics this is called a great-circle distance.</p>
<p>&nbsp;</p>
<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/Geotag-your-Entities-using-Azure-Mobile-_FFE5/image_4.png"><img width="240" height="238" title="image" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/Geotag-your-Entities-using-Azure-Mobile-_FFE5/image_thumb_1.png" border="0" /></a></p>
<p>A good computational approach to calculate the great-circle distance consists of using the <a href="http://en.wikipedia.org/wiki/Haversine_formula">Haversine formula</a>.&nbsp; This formula provides acceptable accuracy and is less susceptible to&nbsp; computational rounding errors when compared to other mathematically correct approaches such as the spherical law of cosines.&nbsp;</p>
<p>&nbsp;</p>
<blockquote>
<p><span style="font-size: small;" size="2">Note: The actual Earth&rsquo;s shape is elliptical, dented at the poles, so although the Haversine formula assumes a perfect sphere, the results are acceptable for most cases.</span>&nbsp;</p>
</blockquote>
<p>&nbsp;</p>
<p>For the implementation, I will use the Haversine formula in combination with a trigonometric approach, that I will introduce for optimization reasons.</p>
<p>&nbsp;</p>
<h3>Enough of Math and Theory, show me the code</h3>
<p>&nbsp;</p>
<p>First I need to create a GeoPoint entity and associate it to my data entity.&nbsp; In this example, I will be using the default template for Azure Mobile Services with a .NET backend.&nbsp; The template has an implementation of a back end for a to-do list.&nbsp; What this means is that I will be attaching geo-location information to to-do items.</p>
<p>Here&rsquo;s the code for the GeoPoint and TodoItem entities.</p>
<p>&nbsp;</p>
<pre class="csharpcode"> <span class="kwrd">public</span> <span class="kwrd">class</span> GeoPoint:EntityData
 {
        <span class="kwrd">public</span> <span class="kwrd">double</span> Latitude { get; set; }
        <span class="kwrd">public</span> <span class="kwrd">double</span> Longitude { get; set; }
  }

 <span class="kwrd">public</span> <span class="kwrd">class</span> TodoItem : EntityData
 {
        <span class="kwrd">public</span> <span class="kwrd">string</span> Text { get; set; }

        <span class="kwrd">public</span> <span class="kwrd">bool</span> Complete { get; set; }

        <span class="kwrd">public</span> <span class="kwrd">virtual</span> GeoPoint Location { get; set; }
 }</pre>


<p>What&rsquo;s really cool is that with this code and relaying on the existing TableController for my TodoItem entity , I can have my mobile application send TodoItems to my back end with geo information attached to them and the information will be persisted in the database, without any more coding!</p>
<p>With the data stored in a database, let&rsquo;s expose an action that allows a client to retrieve the list of items closest to a geo location and within a maximum distance from it.</p>
<p>From the logic&rsquo;s flow perspective, for each item in the database, I need to calculate the distance to the given geo-location and then check if it&rsquo;s less than the maximum distance. Doing this for all the items, implies the need to enumerate all of them,&nbsp; calculate the distance and check if it&rsquo;s less than the maximum distance.&nbsp;</p>
<p>Since calculating the actual distance using the Haversine formula is a complex mathematical operation,&nbsp; in the code below, first I narrowed the list down by using a simpler trigonometric calculation . The trigonometric approach won&rsquo;t provide an accurate distance so we can&rsquo;t use it to determine if it&rsquo;s within the maximum distance requested by the client, however it will provide the list of the closest items to the geo-point nevertheless.</p>
<p>From the narrowed list, I calculate the distance, using the Haversine formula and then determine if it&rsquo;s within range and then return the items to the client.</p>
<p>&nbsp;</p>
<blockquote>
<p><span style="font-size: small;" size="2"><strong>Note: </strong>An additional benefit of this approach is that it also shares the burden of the calculation between&nbsp; the application and database servers. If we calculate the Haversine result within the SQL statement then all the heavy lifting will reside on the database. </span></p>
</blockquote>
<p>&nbsp;</p>
<pre class="csharpcode"><span class="kwrd">public</span> IEnumerable&lt;TodoItem&gt; GetTodoItemsNearGeoPoint(<span class="kwrd">double</span> longitude, <span class="kwrd">double</span> latitude, <span class="kwrd">int</span> count, <span class="kwrd">int</span> maxDistance)
{
            var closest = Query()
               .OrderBy&lt;TodoItem, <span class="kwrd">double</span>&gt;(t =&gt; Math.Pow(longitude - t.Location.Longitude, 2) + Math.Pow(latitude - t.Location.Latitude, 2))
                .Take&lt;TodoItem&gt;(count);

            var withinMaxDistance = <span class="kwrd">new</span> List&lt;TodoItem&gt;();

            <span class="kwrd">foreach</span> (var item <span class="kwrd">in</span> closest)
            {
                var distance = CaculateGreatCircle(longitude, latitude, item.Location.Longitude, item.Location.Latitude);

                <span class="kwrd">if</span> (distance &lt;= maxDistance)
                {
                    withinMaxDistance.Add(item);
                }

            }

            <span class="kwrd">return</span> withinMaxDistance;
        }

<span class="kwrd">private</span> <span class="kwrd">double</span> CaculateGreatCircle(<span class="kwrd">double</span> long1, <span class="kwrd">double</span> lat1, <span class="kwrd">double</span> long2, <span class="kwrd">double</span> lat2)
        {
            var R = 3959; //In Miles           
            var dlong = ToRadians(long1-long2);
            var dLat = ToRadians(lat1-lat2);
            var arc = Math.Sqrt(
                        Math.Pow(Math.Sin(dLat) / 2, 2)
                        +
                        Math.Cos(ToRadians(lat1)) *
                        Math.Cos(ToRadians(lat2)) *
                        Math.Pow(Math.Sin(dlong) / 2, 2)
                    );
            <span class="kwrd">return</span> R * 2 * Math.Atan2(arc,Math.Sqrt(1- arc));
                                       
        }

<span class="kwrd">private</span> <span class="kwrd">double</span> ToRadians(<span class="kwrd">double</span> <span class="kwrd">value</span>)
        {
            <span class="kwrd">return</span> Math.PI * <span class="kwrd">value</span> / 180;
        }
</pre>
<p>Finally,&nbsp; please note that distance is assumed to be in Miles.</p>
<h3>Conclusion</h3>
<p>In this blog post, I show how you can easily associate geo location information to your objects using Azure Mobile Services as well as the implementation of server side logic to retrieve objects that are closest to a given geo-location.</p>]]></content:encoded>
    </item>
    <item>
      <title>Meet the new version of Visual Studio – Visual Studio “14”</title>
      <link>https://docs.microsoft.com/archive/blogs/giventocode/meet-the-new-version-of-visual-studio-visual-studio-14</link>
      <pubDate>Tue, 03 Jun 2014 12:36:38 GMT</pubDate>
      <dc:creator><![CDATA[giventocode]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/giventocode/2014/06/03/meet-the-new-version-of-visual-studio-visual-studio-14/</guid>
      <description><![CDATA[Today, Microsoft released the CTP 1 (Community Technology Preview) of the next version of Visual...]]></description>
      <content:encoded><![CDATA[<p>Today, Microsoft released the CTP 1 (Community Technology Preview) of the next version of Visual Studio, codename Visual Studio “14”. The next version of Visual Studio that includes “Roslyn”, the new <a href="http://roslyn.codeplex.com/">.NET Compiler Platform</a> that builds on a vision of an open-source compiler as a service for VB and C#. </p> <p>The CTP also includes the next version of ASP.NET. <a href="http://www.asp.net/vnext">ASP.NET vNext</a> is a streamlined stack for building modern web applications for both cloud and on premises servers. </p> <p>Visual Studio “14” continues to push forward the Visual C++ compiler on standards conformance for several features such as C++ 11 user-defined literals, inline namespaces, noexcept&nbsp; as well as C++ 14 generalized lambda capture and std::user-defined literals.</p> <p>Please note that these are very early bits and not recommended for production scenarios. For developers is also recommended to install this CTP on a clean machine or VM. Side-by-side installations with Visual Studio 2013 are not allowed.</p> <p><a href="http://blogs.msdn.com/b/somasegar/">Learn More: Soma’s Blog</a> </p> <p><a href="http://go.microsoft.com/fwlink/p/?LinkId=400850">Download: Visual Studio “14” CTP 1</a>  <p><a href="http://go.microsoft.com/fwlink/?LinkId=400496">KB: Visual Studio “14” CTP 1 KB</a>]]></content:encoded>
    </item>
    <item>
      <title>The apps that powered the Lumia Arc of Wonder</title>
      <link>https://docs.microsoft.com/archive/blogs/giventocode/the-apps-that-powered-the-lumia-arc-of-wonder</link>
      <pubDate>Fri, 23 May 2014 20:28:17 GMT</pubDate>
      <dc:creator><![CDATA[giventocode]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/giventocode/2014/05/23/the-apps-that-powered-the-lumia-arc-of-wonder/</guid>
      <description><![CDATA[First blog of the series where I will discuss the apps behind the viral Nokia commercial Lumia...]]></description>
      <content:encoded><![CDATA[<p>First blog of the series where I will discuss the apps behind the viral Nokia commercial Lumia Moments - Arc of Wonder.</p>
<p>Check it out !</p>
<p><a title="From idea to execution..." href="http://giventocode.com/from-idea-to-execution-&ndash;-developing-the-technology-that-drove-the-nokia-lumiamoments-&ndash;-arc-of-wonder#.U4AMOJVOXX4">From idea to execution...</a></p>]]></content:encoded>
    </item>
    <item>
      <title>From Idea to Execution – Developing the technology that drove the Nokia LumiaMoments – Arc of Wonder</title>
      <link>https://docs.microsoft.com/archive/blogs/giventocode/from-idea-to-execution-developing-the-technology-that-drove-the-nokia-lumiamoments-arc-of-wonder</link>
      <pubDate>Thu, 22 May 2014 10:59:00 GMT</pubDate>
      <dc:creator><![CDATA[giventocode]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/giventocode/2014/05/22/from-idea-to-execution-developing-the-technology-that-drove-the-nokia-lumiamoments-arc-of-wonder/</guid>
      <description><![CDATA[It&rsquo;s not every day that you are given the opportunity to help execute an idea to recreate the...]]></description>
      <content:encoded><![CDATA[<p>It&rsquo;s not every day that you are given the opportunity to help execute an idea to recreate the infamous &ldquo;famous bullet&rdquo; effect from the Matrix using a very different set of tools: 50 Lumia 1020s. This effect would be the star of the new advertisement for the <a href="https://www.youtube.com/watch?v=LmDNjZM3Tu8">Lumia</a>. What came next was an interesting app development challenge that would inevitably showcase the productivity of Microsoft&rsquo;s development platform and tools. The goal? To create a camera app that would take full resolution pictures from all 50 phones, all at the same time, to capture 50 different perspectives of the same moment in time. Challenge accepted.</p>
<p>&nbsp;</p>
<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/What-would-you-do-in-NYC-with-50-Lumia-1_10203/WP_20140405_15_26_12_Pro_2.jpg"><img width="640" height="360" title="WP_20140405_15_26_12_Pro" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" alt="WP_20140405_15_26_12_Pro" src="http://giventocode.com/Media/Default/Windows-Live-Writer/What-would-you-do-in-NYC-with-50-Lumia-1_10203/WP_20140405_15_26_12_Pro_thumb.jpg" border="0" /></a></p>
<p>&nbsp;</p>
<h3>Creative Iterations</h3>
<p>&nbsp;</p>
<p>&ldquo;Fail fast&rdquo; was the mantra. An aggressive schedule demanded the fail fast mindset. We had to think simplest way to achieve the goal and try it. Ensuring that all the phones could capture a sequence of pictures with a latency of less than 50ms(1ms is a 1000th of a second) was not a simple goal. We wanted to avoid point to point connections to each device to push the &ldquo;shutter&rdquo;. The rationale behind this was that in such cases, the triggering app would have to sequentially enumerate each connection to send data, hence introducing the risk of triggering delays between the first and last devices.</p>
<p>&nbsp;</p>
<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/What-would-you-do-in-NYC-with-50-Lumia-1_10203/WP_20140324_17_29_31_Pro_5.jpg"><img width="640" height="360" title="WP_20140324_17_29_31_Pro" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" alt="WP_20140324_17_29_31_Pro" src="http://giventocode.com/Media/Default/Windows-Live-Writer/What-would-you-do-in-NYC-with-50-Lumia-1_10203/WP_20140324_17_29_31_Pro_thumb_1.jpg" border="0" /></a></p>
<p>&nbsp;</p>
<p>Initially, we considered an approach where we would rely on the device&rsquo;s clock and schedule when the picture will be taken. The phones would then poll a cloud resource to receive the time they need to take the picture.&nbsp; We quickly realized that the devices were off by a few seconds despite having clock syncing enabled. We wanted to give this approach another try so we implemented a time adjustment algorithm that uses a central point of reference in the cloud. Even though we brought the latency down to 150ms, we were&nbsp; still off from our goal.</p>
<p>At this point, we iterated again and began to work on a new solution based on network multicasting. Network multicasting is a form of networking communication where the data is addressed simultaneously to a group of devices.</p>
<p>&nbsp;</p>
<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/What-would-you-do-in-NYC-with-50-Lumia-1_10203/WP_20140324_17_28_34_Pro_5.jpg"><img width="640" height="306" title="WP_20140324_17_28_34_Pro" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" alt="WP_20140324_17_28_34_Pro" src="http://giventocode.com/Media/Default/Windows-Live-Writer/What-would-you-do-in-NYC-with-50-Lumia-1_10203/WP_20140324_17_28_34_Pro_thumb_1.jpg" border="0" /></a></p>
<p>&nbsp;</p>
<p>The new approach showed promising results in our first tests.&nbsp; Odd discrepancies between certain devices had to be tackled, caused by the camera&rsquo;s flash and the automatic lighting adjustment of the device. But after a few iterations of tweaks we were able to meet our latency goal!</p>
<p>The iterative process coupled with Visual Studio enabled us to adapt quickly, code with superb productivity and implement these ideas with a few lines of code.</p>
<p>&nbsp;</p>
<h3>One Controller to Control them All</h3>
<p>&nbsp;</p>
<p>Each phone runs a custom camera app built from the grounds up for this project that takes advantage of the Lumia&rsquo;s 1020 maximum picture resolution. The app listen listens for a network &ldquo;trigger&rdquo;&nbsp; that fires the camera and saves the picture in the device.</p>
<p>A key concern was avoiding manipulating the devices once they were mounted on the rig. The rig is a custom built metal&nbsp;arc where each device was purposely placed to take a 180 degrees&rsquo; perspective of the same moment in time. Great for making the effect possible, but not for manipulating each device individually, therefore having the ability to set the camera's settings&nbsp;for all the devices from a central location was a chief goal.&nbsp; So&nbsp;taking advange of the same networking&nbsp;approach&nbsp;we&nbsp;used for the trigger we implemented&nbsp;a mechanism where each device would "listen" for the&nbsp;camera settings as well.</p>
<p>&nbsp;</p>
<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/What-would-you-do-in-NYC-with-50-Lumia-1_10203/WP_20140402_15_23_57_Pro_2.jpg"><img width="640" height="360" title="WP_20140402_15_23_57_Pro" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" alt="WP_20140402_15_23_57_Pro" src="http://giventocode.com/Media/Default/Windows-Live-Writer/What-would-you-do-in-NYC-with-50-Lumia-1_10203/WP_20140402_15_23_57_Pro_thumb.jpg" border="0" /></a></p>
<p>&nbsp;</p>
<p>Like any project, the aggressive schedule kept looming while the list of new challenges was growing. One of those challenges was to figure out how the director would trigger the shooting sequence and the broadcasting of the camera settings.This functionality was better achieve with a bigger form factor made sense and a Surface was the natural choice.</p>
<p>From the development&rsquo;s perspective, this meant that we had to create another app. This app would need to send the execution trigger as well as the camera settings to all the phones. For this purpose, the WinRT networking APIs provided us with the stepping stone that we needed to create a Windows Store App in a very short period of time.</p>
<h3>&nbsp;<a href="http://giventocode.com/Media/Default/Windows-Live-Writer/What-would-you-do-in-NYC-with-50-Lumia-1_10203/image_5.png"><img width="640" height="241" title="image" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" alt="image" src="http://giventocode.com/Media/Default/Windows-Live-Writer/What-would-you-do-in-NYC-with-50-Lumia-1_10203/image_thumb_1.png" border="0" /></a></h3>
<p>&nbsp;</p>
<h3>Testing with 50 Devices</h3>
<p>But, wait, how do you measure latency? Specially considering that the internal clocks of the devices could be out of sync by a few seconds and this rules out any time-stamp or logging mechanism generated from the phones. An impossible task?&nbsp; Well, not really. Our solution was quite simple. To test, we pointed the cameras to a large screen displaying a stopwatch counting down to the milliseconds. Once we&rsquo;ve triggered the capture, we checked the time value captured in each photo.&nbsp; Latency measured!</p>
<p>With so many individual moving parts, there was no way we could anticipate the number and types of issues we were going to face once the components were integrated and tested as a whole. The first challenge we encountered was the arm which held the phone on the rig obstructed the viewfinder. To fix this issue, we made the viewfinder resizable.</p>
<p>&nbsp;</p>
<p><a href="http://giventocode.com/Media/Default/Windows-Live-Writer/What-would-you-do-in-NYC-with-50-Lumia-1_10203/WP_20140403_18_36_21_Pro_2.jpg"><img width="640" height="360" title="WP_20140403_18_36_21_Pro" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" alt="WP_20140403_18_36_21_Pro" src="http://giventocode.com/Media/Default/Windows-Live-Writer/What-would-you-do-in-NYC-with-50-Lumia-1_10203/WP_20140403_18_36_21_Pro_thumb.jpg" border="0" /></a></p>
<p>&nbsp;</p>
<p>A more pressing concern was that we could not get a good sense of whether the devices were receiving the execution trigger and the settings. With the multicasting mechanism we had low latency to the expense of reliability. So we decided to show on each device a running log of what was received so we check after each shooting.</p>
<p>Simply put, we strived towards finding simple and practical solutions to our challenges.</p>
<p>&nbsp;</p>
<h3>Shooting Day</h3>
<p>At the shooting, the hard work paid off and the applications performed as expected, delivering foundation for the awesome video that <a href="http://paultrillo.com/">Paul Trillo</a> created.</p>
<p>&nbsp;</p>
<div class="wlWriterEditableSmartContent" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:9f738ebc-ad1b-4541-a766-f6bb9883e3eb" style="float: none; margin: 0px; display: inline; padding: 0px;">
<div><object width="629" height="353"><param name="movie" value="https://www.youtube.com/v/LmDNjZM3Tu8?hl=en&amp;hd=1" /></object><embed width="629" height="353" src="https://www.youtube.com/v/LmDNjZM3Tu8?hl=en&amp;hd=1" type="application/x-shockwave-flash" /></div>
<div style="width: 629px; clear: both; font-size: .8em;">Living Moments Lumia Arch of Wonder #Lumia Moments</div>
</div>
<p>&nbsp;</p>
<h3>Wrapping up!</h3>
<p>&nbsp;</p>
<p>In this blog post, I provided you a quick overview into how we approached the creation of software for the Lumia Moments commercial. In my next blog posts, I will dive deeper into some key aspects of the implementation of the software.</p>
<p>Stay tune!</p>
<p>&nbsp;</p>
<p><em>Update: I made some changes to this blog post since I first published it to include some additional details about the phone app and how we tested latency.</em></p>]]></content:encoded>
    </item>
  </channel>
</rss>