#[ SOLVED ] Examine: Exact Node Name only?

1 messages ยท Page 1 of 1 (latest)

rare yacht
#

Hi! Following on from yesterday's exciting post I'm back with another Examine question.

Is there a way to specify "Search for exactly this NodeName, don't return anything else unless it's exactly the same"? Found that searching "Article" would also give nodeNames like "Article About Umbraco" - which, while handy, isn't ideal for the use case of checking if a node called "Article" currently exists.

Code as is - goal is to only get a node with the NodeName as an exact match. To this end I've now added the extra if/foreach validation against the search result's "AllValues" dict, which feels cursed to say the least.

var folderSearchResult = index
    .Searcher
    .CreateQuery(Umbraco.Cms.Infrastructure.Examine.IndexTypes.Media)
    .NodeTypeAlias(Folder.ModelTypeAlias)
    .And()
    .NodeName(nameOfFolder)
    .And()
    .ParentId(rootFolderId)
    .Execute();

if (folderSearchResult != null)
{
    foreach (var folderResult in folderSearchResult)
    {
        var nodeName = folderResult.AllValues["nodeName"].FirstOrDefault();
        if (nodeName != null && nodeName.Equals(nameOfFolder))
        {
            return int.Parse(folderResult.Id);
        }
    }
}

TIA!

thorn juniper
#

This is to do with how nodeName is indexed, you can't do an exact match against it because examine/lucene doesn't actually know what that field says - it sees a tokenized list of what's inside it.

Just to check - what 's this for and how reliable does it need to be?

This seems like a very specific use case for a "search" and since you already know the parent id, fetching what you need straight out of the cache may be both simpler and safer.

rare yacht
#

Hi Jason, thanks for your reply.

Specific case:

  • I'm migrating blog articles where each blog article is made up of a folder, containing a markdown file (the blog's content) and an image (the hero image for the blog)
  • I'm running this migration by looping over the blog folders and creating through ContentService
  • For each of these blog folders I'm wanting to create a folder in Media, under the folder "Blog", with the name of the blog (i.e. ~/Blog/BlogName/)
  • Before creating the Media folders I want to check whether that specific folder (~/Blog/BlogName/) exists - essentially a GetOrSet action for that specific folder

So in this instance, the "search" has to be exact - if it's a case of instead querying mediaService instead of Examine then cool, I'm just getting used to when to use which type of search and for what.

Does that make sense? Would appreciate your input. TIA!

rare yacht
#

My attempt through querying the cache w UmbracoHelper is this:

public IPublishedContent? GetBlogArticleFolder()
{
    var rootFolder = UmbracoHelper.MediaAtRoot().FirstOrDefault(x => x is { Name: "Blog", ContentType: Folder.GetModelContentType(_publishedSnapshotAccessor) });

    return rootFolder?.Descendants<Folder>().FirstOrDefault(x => x.Name is "Article Name To Find");
}

Would this be the correct way to find the child of a media item called "Blog" which is a folder called "BlogName"?

buoyant patio
#

So:

  • Examine - tokenized search
  • UmbracoHelper - querying against cache (note: for Content, items have to be published first, media items are always in a published state)
  • Content/MediaService - querying against the db directly (when looking for content that is not yet published / the version you need is in draft)

And your code looks correct ๐Ÿ‘

Ps. did you know if you write csharp after the first 3 backticks you get nice code highlighting? ๐Ÿ˜

rare yacht
#

Brilliant, thank you on all counts!

rare yacht
#

[ SOLVED ] Examine: Exact Node Name only?

thorn juniper
#

Nice, I always forget about is

thorny gale
#

Examine can do exact matches, the index and query time analysers for the field do need to not do any stemming etc. Raw field type.

celest knoll
#

there is phrase matching in examine too.. though note the indexer stores as lower case.

.CreateQuery(Umbraco.Cms.Infrastructure.Examine.IndexTypes.Media)
    .NodeTypeAlias(Folder.ModelTypeAlias)
    .And()
    .NodeName(nameOfFolder.ToLower().Escape())
    .And()
    .ParentId(rootFolderId)
    .Execute();

if you look at the query generated from
.Field("someField", "Article Name To Find") it actually ends up being somefield is "article" or "name" or "to" or "find" due the the fluent examine parsing? or just examine itself

nodeName is already a raw field I think so Escape() should work for the phrase matching but if you needed it for other fields..

thorn juniper
#

nodeName isn't a raw @celest knoll

In the case of two nodes:
1: "Page"
2: "Another Page"
NodeName("page".Escape()) will return both.

Adding other/extra raw fields though is a great way to look up things like product SKUs, exact name etc. or pulling content from anywhere on the tree based on a property value (you can actually mimic one-to-many/one relationships using examine to do a reverse lookup, which is really cool.)

celest knoll
thorn juniper
#

Unfortunately yes, it's tokenized.