Try our conversational search powered by Generative AI!

Manoj Kumawat
Feb 27, 2023
  1201
(2 votes)

Deleting missing metafields in code programmatically

This blog post will help you in deleting meta fields programatically in catalogue context. We will only delete metafields which are user generated and missing from code (deleted later in the code) but remain in database. 

#1 - get the list of metaclasses (user generated) 

    private readonly Mediachase.MetaDataPlus.Configurator.MetaClassCollection _metaClassCollection;

    _metaClassCollection = Mediachase.MetaDataPlus.Configurator.MetaClass.GetList(CatalogContext.MetaDataContext, true);

    _metaClassCollection.Cast<Mediachase.MetaDataPlus.Configurator.MetaClass>()
                .Where(c => c.IsUser
                && c.MetaFields.Any(x => x.IsUser))

The above collection will fetch meta classes created by the user and any of it's metafields is user generated at least. 

#2 - Getting metafields for class

     metaClass.MetaFields
     .Where(c => c.IsUser && c.OwnerMetaClassIdList.MetaCollectionHasOnly(id))

Above code snippet selects all the meta fields for a metaclass and makes sure it is not fetching any other metafield under a class which comes from relation of the same class (i.e. product > Category > Catalog)
Therefore, It only displays meta fields strictly which are part of the class. I've used an extension method that makes sure each metafiled has only 1 exact same parent as current class. 

 public static bool MetaCollectionHasOnly(this MetaClassIdCollection collection, int classId)
    {
        try
        {
            if (collection != null && collection.Count == 1)
            {
                return collection[0] == classId;
            }

            return false;
        }
        catch
        {
            //we don't want to catch exception in this case.
            return false;
        }
    }

Now it comes to the final step which is most important - Identify missing field from class

Each metaclass is mapped with contentType class you have in your code. Here we need to figure out which class in code is mapped with metaclass in database. Let's understand it easy way -

If I have a base class for all the products in the code as ProductBase with [CatalogContentType] decorator then for MetaClass Product MetaClassToContentTypeMap will fetch ProductBase.

Now the only thing you need to check if the metafield exists in the code as follows - 

private readonly Injected<MetaClassToContentTypeMap> _contentTypeModelRepository;

public string MetaFieldName { get; set; }
private Type ClassType
    {
        get
        {
            return _contentTypeModelRepository.Service.GetContentTypeModel(MetaClassId);
        }
    }

    public bool IsAvailable 
    {
        get
        {
            return ClassType.HasProperty(this.MetaFieldName);
        }
    }

IsAvailable property returns whether the metafield exists in the code or not. 

--------------------------------------------------------------

Update - Deleting what we have detected so far. In my project I had an endpoint which would do it for me. The field you want to delete, send it along with it's parent classId. 

 [HttpPost]
    [Route("metafields/{classId}/delete/{fieldId}", Name = "DeleteMetaField")]
    public JsonResult Delete(int classId, int fieldId)
    {
        var result = false;

        try
        {
            var metaClass = _metaClassCollection.Cast<Mediachase.MetaDataPlus.Configurator.MetaClass>()
                .FirstOrDefault(c => c.Id.Equals(classId));

            if (metaClass != null)
            {
                var metaField = metaClass.MetaFields.FirstOrDefault(c => c.Id.Equals(fieldId));
                metaField.Delete();
            }

            result = true;
        }
        catch (Exception ex)
        {
            Log.Error("Failed to delete" + ex.Message);
            result = false;
        }
        return new JsonResult(result);
    }

And the extension method to delete: 

public static class MetaFieldExtensions
{
    private static readonly MetaDataContext Context = CatalogContext.MetaDataContext;

    public static void Delete(this MetaField metaField)
    {
        if (metaField == null)
        {
            return;
        }
        foreach (var metaClassId in metaField.OwnerMetaClassIdList)
        {
            var cls = Mediachase.MetaDataPlus.Configurator.MetaClass.Load(Context, (int)metaClassId);
            cls.DeleteField(metaField);
        }

        MetaField.Delete(Context, metaField.Id);
    }
}

Hope this helps. 

Feb 27, 2023

Comments

Marcin
Marcin Apr 7, 2023 09:26 AM

@Manoj 

Thanks for the article. In the title I see "Deleting missing metafields in code programmatically", but from the article I only learned how to detect properties that are still in the database, but not in the code. Could you extend the article with more information on how to get rid of such unused properties?

In my case, after using Commerce for a long time, I am dealing with properties that are not used - sometimes they are single, sometimes there are more. I would like them not to be displayed as well as get rid of them from the database to speed up the performance of the products - currently, by handling existing obsolete properties, the products seem to run slower.

Manoj Kumawat
Manoj Kumawat Apr 20, 2023 07:47 AM

Marcin, Just updated it. Hope it helps!

Please login to comment.
Latest blogs
From Procrastination to Proficiency: Navigating Your Journey to Web Experimentation Certification

Hey there, Optimizely enthusiasts!   Join me in celebrating a milestone – I'm officially a certified web experimentation expert! It's an exhilarati...

Silvio Pacitto | May 17, 2024

GPT-4o Now Available for Optimizely via the AI-Assistant plugin!

I am excited to announce that GPT-4o is now available for Optimizely users through the Epicweb AI-Assistant integration. This means you can leverag...

Luc Gosso (MVP) | May 17, 2024 | Syndicated blog

The downside of being too fast

Today when I was tracking down some changes, I came across this commit comment Who wrote this? Me, almost 5 years ago. I did have a chuckle in my...

Quan Mai | May 17, 2024 | Syndicated blog

Optimizely Forms: Safeguarding Your Data

With the rise of cyber threats and privacy concerns, safeguarding sensitive information has become a top priority for businesses across all...

K Khan | May 16, 2024

The Experimentation Process

This blog is part of the series -   Unlocking the Power of Experimentation: A Marketer's Insight. Welcome back, to another insightful journey into...

Holly Quilter | May 16, 2024

Azure AI Language – Sentiment Analysis in Optimizely CMS

In the following article, I showcase how sentiment analysis, which is part of the Azure AI Language service, can be used to detect the sentiment of...

Anil Patel | May 15, 2024 | Syndicated blog