Azure search schema migrations [closed] - azure

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
What's the best way to migrate an Azure search schema in a release pipeline?
In the SQL world, I'd use something like DbUp. Is there anything similar for Azure search?
Or is there a different approach when the schema needs to change?

It depends on whether you are pushing content via the SDK or if you are pulling content from a supported content source using one of the pre-built indexers. Using the SDK you can add new properties to your model as explained in this post: Update Azure search document schema
Note: Changes in your data model may require either an update or a rebuild of the index. For example, adding new properties only requires and update. But, if you change a setting like searchable, filterable or sortable you will need a rebuild. For details, see How to rebuild an index in Azure Cognitive Search
COMPATIBILITY PROBING VIA PUSH
My preferred solution is to use push indexing for everything. To test if the data model in the index is compatible, I create a sample item and submit to the index. If the model used in the index is incompatible, and error is thrown by the Azure Search SDK. I then delete the index and create it from scratch using my new model.
Here is a simplified method to test if any item is compatible with a named index:
public async Task<bool> TestItemAsync<T>(T item, string indexName)
{
var isCompatible = false;
var indexClient = _searchServiceClient.Indexes.GetClient(indexName);
var indexActions = new List<IndexAction<T>> { IndexAction.MergeOrUpload((item)) };
var batch = IndexBatch.New(indexActions);
try
{
var unused = await indexClient.Documents.IndexAsync(batch);
isCompatible = true;
}
catch
{
// ignored
}
return isCompatible;
}
And here is an example of how you might use it to probe your index for compatibility.
var item = new Product();
item.ID = 123;
item.Title = "Sample";
item.MyNewProperty = "Some value"
// ...
var isCompatible = await TestItemAsync(item, indexName);
if (isCompatible)
{
await DeleteItemAsync(item, indexName);
}
else
{
await DeleteIndexAsync<T>(indexName);
await CreateIndexAsync<T>(indexName);
}
To actually verify the compatiblity, make sure you populate your item with some values. In this example I hard-coded some values for the sake of the example. In actual use I use a Mock framework that populates every property of my item with some random sample value, but I did not want to give the impression that a third-party component is required for this use-case.

Related

json find object by name and grab its value (api) [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
i am grabbing the steam data and saving it to variable called body
now what i want to do is find total_kills its not necessary that this object is always at body.playerstats.stats[0].value so is there any way to find the body by total_kills and get its value
the complete api reply is given below with beautified form
https://codebeautify.org/jsonviewer/cb2b563d
It seems like body.playerstats.stats is an Array that contains objects. What you could do is go through that array and store all the objects that have name: 'total_kills', something like this could work:
const totalKillsArr = body.playerstats.stats.filter((stat) => {
return stat.name === 'total_kills';
});
Once you have the new array of totalKills you can use reduce to get the sum of all total kills:
const sumTotalKills = totalKills.reduce((sum, el) => {
sum += el.value;
return sum;
}, 0);
If there is only one object in the stats array that has the name of total_kills then just use a simple find function on the main array like this:
const totalKills = body.playerstats.stats.find(stat => {
return stat.name === 'total_kills';
});
This will find you the first object with name property of total_kills. If there is no such object it will return undefined.

Orchard background task not persisting PartRecords to the database

I'm trying to use a background task to gather Likes/Comments from the Facebook Graph APi and use that to drive our blog's trending.
Here the trendingModels have already been populated and are being used to fill in the TrendingParts.GraphId and TrendingParts.TrendingValue.
I'm not getting any exceptions and the properties on TrendingPart point to the fields in the TrendingPartRecord.
Yet nothing persists to the database, any ideas why?
_orchardsServices is IOrchardServices
var articleParts = _orchardService.ContentManager.GetMany<TrendingPart>(
trendingModels.Select(r => r.OrchardId).ToList(),
VersionOptions.Published,
QueryHints.Empty);
// Cycle through the records and update them from the matching model
foreach (var articlePart in articleParts)
{
ArticleTrendingModel trendingModel = trendingModels.Where(r => r.OrchardId == articlePart.Id).FirstOrDefault();
if(trendingModel != null)
{
// Not persisting to the database, WHY?
// What's missing?
// If I'm understanding things properly nHibernate should push this to the db autoMagically.
articlePart.GraphId = trendingModel.GraphId;
articlePart.TrendingValue = trendingModel.TrendingValue;
}
}
Edit:
It's probably worth noting that I can update and publish the fields on the TrendingPart in the admin panel but the saved changes don't appear in the MyModule_TrendingPartRecord table.
The solution was to change my Service to a transient dependency using ITransientDependency.
The service was holding a reference to the PartRecords array and because it was treated as a Singleton it never disposed and the push to the database was never made.

How to check if Object already exist?

I am importing products from a product feed. A product has a designer and a category and I made them separate tables (Parse classes).
The problem now is that I need to check if a category or designer already exists so I don't need to create it.
Currently I am not checking it, causing many duplicates in my DB. If I checked in DB, it would be asynchronous but I actually need it to be somehow sequential(serialized).. Any ideas?
for (var i=1;i<productsFromFeed.length;i++){
productId = parseInt(productsFromFeed[i][1]);
if (productId > lastProduct.get("productId")){
console.log("Product is new: " + productId);
var Designer = Parse.Object.extend("Designer");
var Product = Parse.Object.extend("Product");
var Category = Parse.Object.extend("Category");
var designer = new Designer();
designer.set("name", productsFromFeed[i][4]);
designer.set("designerId", parseInt(productsFromFeed[i][5]));
var category = new Category();
category.set("name", productsFromFeed[i][6]);
category.set("categoryId", parseInt(productsFromFeed[i][7]));
var newProduct = new Product();
newProduct.set("productName", productsFromFeed[i][0]);
newProduct.set("productId", parseInt(productsFromFeed[i][1]));
newProduct.set("designer", designer);
newProduct.set("category", category);
objects.push(newProduct);
} else {
console.log("Product already exists: " + productId);
}
}
It doesn't need to be serial, you just need to deal with the asynchronous nature of what you're trying to do - using promises.
You could run a query to find everything in advance and locally cache them, that's only useful if you're doing a bulk import, your code does look like a small bulk import but it isn't clear if this will be an efficient approach.
In your case just run your queries and use promises to chain each logical stage together. Note that for your loop you can put the resulting promises into an array and wait till they're all complete.

Unable to Retrieve “two option” values on plugin - CRM 2011 [duplicate]

This question already has answers here:
Retrieving "two option" field value on the plugin in CRM 2011
(4 answers)
Closed 9 years ago.
I'm unable to retrieve "two option" field's selected value on plugin using the following code
bool? update = entity.GetAttributeValue<bool?>("new_updatecontacts");
bool update = entity.GetAttributeValue<bool>("new_updatecontacts");
if (update)
{
..................
}
Is there any other way of retrieving the same? I have already posted the same question, but did not get a definite answer, so am asking again.
By default, a plugin only contains the values for fields that have been added/updated. For other events you get other properties but let's go with that for now.
So if you want to be sure you have a value, you need to run off to CRM to get a copy.
var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
var serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
var service = serviceFactory.CreateOrganizationService(context.InitiatingUserId);
var target = context.InputParameters["Target"] as Entity;
if (!target.Contains("new_updatecontacts"))
{
target = service.Retrieve(target.LogicalName, target.Id, new ColumnSet(new [] { "new_updatecontacts", "other_required_fields_here" });
}
//now you know it is present
It is worth checking if it is there first as it saves a server hit.

Backbone.relational, real-time and handling large data

I'm building a real-time feed application using Backbone.js, node.js and socket.io.
My Feed is a collection of Update models. Displaying these, overriding Backbone.sync for integration with socket.io works fine.
The complication comes in that each Update has a set of comments associated with it. When I show each Update in the Feed view, I want to show a summary of the associated comments (number of comments and a single 'most poular' comment), and also have the ability to click through to a different view to display each Update on its own with a paginated list of comments with further data.
I'm using backbone-relational to model the relationship between the Update model and Comment model, as follows:
Feed (collection) -> Update (model) -(has many)-> Comment (model)
I've been following this backbone-relational tutorial, but it seems to assume that I'd want to have all related data in memory at once in my Feed view, which I don't as there are potentially thousands of comments updating in real-time:
http://antoviaque.org/docs/tutorials/backbone-relational-tutorial/
My questions are:
How can I bring in summary data for comments to each Update in my Feed view without loading all comment data, and also maintain the ability to show paginated full data in my Update view?
I'm using backbone.layoutmanager for rendering my views. How best should I break my views up to accomplish the above?
For Q1:
I'm assuming you're using something like ioSync to use socket.io in Backbone.sync instead of REST API, or a similar solution.
Include metadata (such as # of comments) as an attribute on Update. If your Update object is heavy weight in itself, you could update the count using ioBind and custom server-side socket.io events instead of sending the whole object every time.
Include an attribute topComment as an additional one-to-one relation in Update. When initially loading Update from the server, include topComment in the response, but not the other comments.
Lazy-load the rest of the comments using custom socket.io events. You will likely want a server-side handler that takes as parameters updateId, startIndex, maxComments, which returns a list of comments for the given Update starting at the given index. If the result is sent to the client as JSON, then it's easy to do something like this on the client:
// Assume `model` is an instance of `Update`.
socket.emit('get_comments_page', {
updateId: model.get('id'),
startIndex: 1,
maxComments: 10
}, function(err, data) {
if (err) {
alert('Unable to fetch comments: ', err);
} else {
model.get('messages').reset(data)
}
});
Avoid sending ID for all comments when fetching Update then trying to use fetchRelated to resolve them. I learned this one the hard way :O/
You could also store the comments collection directly on the view without associating it as relationship of Update
For Q2:
I don't have any experience with layoutmanager as I use Backbone.Marionette for managing my views. Marionette has an async extension (disclaimer: I'm a co-maintainer). I encourage to see how Marionette.async does the delayed rendering, waiting for the data to arrive from the server.
The main idea is to use jquery's Deferred objects that resolve when the data comes back from the server. Extending the above example with deferred:
var MyView = Backbone.View.extend({
// ... normal stuff that views need ...
initialize: function() {
var deferred = $.Deferred();
// Assume `model` is an instance of `Update`.
var that = this;
socket.emit('get_comments_page', {
updateId: that.model.get('id'),
startIndex: that.options.pageNumber,
maxComments: 10
}, function(err, data) {
if (err) {
alert('Unable to fetch comments: ', err);
} else {
that.model.get('messages').reset(data)
}
deferred.resolve();
});
this.promise = deferred.promise();
},
render: function() {
var that = this;
this.promise.done(function() {
// Do your normal rendering code here, for instance:
$(that.el).html(that.template(that.model.toJSON()));
});
return this;
}
});
Note: the code snippets above are not tested as is.

Resources