Showing posts with label People Search. Show all posts
Showing posts with label People Search. Show all posts

Friday, October 27, 2023

Using PnP Modern Search to display today's work anniversaries

In a way this is part 2 on how to using PnP Modern Search to display days of celebration. In Using PnP Modern Search to display today's birthdays I showed how to display birthdays, so a natural progression is to show how to display work anniversaries.


I was really surprised how difficult this proved to be. I even discussed the topic with Mikael Svenson and Marc Anderson and I realized that I had to cheat in order for it to work.


The problem is that date manipulation in KQL is hard at best and sometimes impossible. In order to find a work anniversary I must compare Today and the Hiredate managed property, but ONLY the day and month part.

Calculating how many years the employee has been with the company is also required and I have NO idea how to get that using KQL.
























Objective

I wanted to be able to display two options: 
  • Employees having a work anniversary today, and also how many years they have been with the company
  • Employees having a work anniversary within the next 7 days + number of years.

How to cheat

In order to achieve the objectives, I had to get:
  • The account 
  • The hiredate, but with the year segment being the current year
  • The number of years the employee has been with company at the next anniversary




 










I added birthdayThisYear while I was at it, in order to be able to show upcoming birthdays.


The basic idea is that I change the hiredate from eg. 10/26/2005 to 10/26/2023 as that allows me to compare Today with this value ๐Ÿ˜€
(RefinableDate12 is mapped to the HiredateThisYear property)

Who is having a work anniversary today?
RefinableDate12=Today

Anniversary within the next x days is also a piece of cake:
 RefinableDate12<{Today+7} AND RefinableDate12>{Today}

Implementation

Asking the intern to keep the list above in sync would be a cruel and unusual punishment, and hence actually forbidden in the USA, something to do with a constitution or something like that.

The list should of course be synced with the source, in this case the User Profile Application, at least once each month. The reason I am not using Graph is that birthday is not in the schema.







Prereq: Map SPS-Birthday and SPS-Hiredate to RefinableDate00/01

Once data is showing up in those RefinableDate properties you should be ready to create the list.
Grab the script here . It will create a few Site Columns and a Content type on the site collection of your choosing. The list is then created, and the Content type added to the list.
The Add-UserDataToList function will query the UPA for accounts and write the data we need to the list.
 
Hit the Reindex site in the site collections Search and Offline Availability section for the site columns to be picked up by search.

Map the crawled properties to a couple of RefinableDates. I prefer to make this mapping on the tenant level as I usually don't know where I might need them in the future. 

Find the Content Type ID of the Content type created by the script.


Add a Results web part, name it "Todays work anniversaries"

Set the Query template to: 

Contenttypeid:0x01009290F0FA40E7CB42B55D6D96F897262B* RefinableDate12=Today

(replace 0x01009290F0FA40E7CB42B55D6D96F897262B with the value for the your content type) 

Add a Results web part, name it "Upcoming anniversaries (7 days)"

Set the Query template to: 

Contenttypeid:0x01009290F0FA40E7CB42B55D6D96F897262B* RefinableDate12<{Today+7} AND RefinableDate12>{Today}

(replace 0x01009290F0FA40E7CB42B55D6D96F897262B with the value for your content type) 


Add the managed properties birthdayhiredateAccountOWSUSER, nextWorkAnniversaryInYearsOWSTNMBR, RefinableDate10, RefinableDate12 to the Selected Properties in both web parts.

Enter Layout slots

Change UserEmail to use the  birthdayhiredateAccountOWSUSER property

Change Date from Created to RefinableDate12


For both web parts you can select the People layout on "page 2" in the web part configuration.

Set Secondary text to: 

{{{Title}}} has been with us {{{nextWorkAnniversaryInYearsOWSTNMBR}}} years

(remember to click Use Handlebars expression)

Set Tertiary text to:

{{getDate (slot item @root.slots.Date) "MMMM-D"}}

(remember to click Use Handlebars expression)

Set the sorting on the Upcoming Anniversaries to RefinableDate12 asc


Run the Add-UserDataToList  function in a runbook or similar once a month and you should be done๐Ÿ˜Š

Sunday, October 22, 2023

Using PnP Modern Search to display today's birthdays

 

In the PnP Modern Search Repository bigbear48858 asked about a separate web part for showing birthdays and work anniversaries: 

Looking for help on filters for pnp search · microsoft-search/pnp-modern-search · Discussion #3300 (github.com)



That got me thinking about how to set up a Search Result web part to display today's birthdays.


The tricky part is that in the User profile application the birthday value is store is a rather usual datatype "date no year"








In my tenant the SPS-Birthday property was mapped to RefinableDate00 and the actual value in the property is 2000-[the date]:

(I used the magnificent SP Editor tool to inspect the managed properties)


So, the query had to be something like "those accounts where RefinableDate00 = 2000 + the value of today's date


In KQL we have the token "today" that will give us today's date, but as far as I know, we can't get the components the date consist of, like Month and Day.

Luckily, the PnP Modern search provides additional Tokens, see Tokens - PnP Modern Search (v4) (microsoft-search.github.io)


So the final query is:

RefinableDate00=2000-{CurrentMonth}-{CurrentDate}T00:00:00Z

            ( and of cause a criteria to exclude former employees, like SPS-HideFromAddressLists<>1) 


















This scenario will be added to the PnP Modern Search documentation ASAP :-)

Monday, May 22, 2023

SharePoint People search - How to clean up your results by exclude accounts


People search in SharePoint is based on the accounts you can see in the User Profiles blade in the SharePoint Admin center



And as you properly know the accounts in the User Profiles will very often be a mess of expired accounts, Meeting Room, External users, Test account and a lot more.


These are my notes for cleaning up the People/Employee search in SharePoint 



Exclude former employees

“SPS-HideFromAddressLists” originates in Exchange and is primarily used to decide which accounts that should not be shown in the Global Address list. In many companies/orgs this property is set to true/1 when somebody leaves the org.

This makes it a very useful property as it is the best indicator we have on whether an account is active or not.

"SPS-HideFromAddressLists"<>1  (show only accounts that should not be hidden in the GAL)

Exclude test, admin or similar accounts

-preferredname:admin*

-preferredname:test*


Exclude accounts which does not use a specific email domain

This filter is an excellent way to exclude external users and consultants with a full account within the org. Please note that we often exclude accounts by specifying that the field should contain a specific value.

WorkEmail:@contoso.com 


Exclude members of a specific department

-Department:External

-Department:Management

Exclude accounts which does not have a value in a given property

It is possible to define a query that will exclude the accounts that do not have any value in a specific field.

Since KQL (the Language we are using in the search queries) can't search for "Fields which does not contain any value" we have to use a little trick:

If we want to exclude the accounts that does not have a cell phone number, we simply must reverse that requirement, and hence it will be "include those accounts that have a value in the cell phone field":

(MobilPhone:0* OR MobilPhone:1* OR MobilPhone:2* OR MobilPhone:3* OR MobilPhone:4* OR MobilPhone:5* OR MobilPhone:6* OR MobilPhone:7* OR MobilPhone:8* OR MobilPhone:9*)


User Profile properties such as Department and JobTitle are based on Term Store Term sets and we can use the Term Guid values in our query.

In this example we are using the auto generated  property owstaxIdSPShDepartment and the guid specified is the root node of the Department term set: (look in the Term Store for those guids)

owstaxIdSPShDepartment:"#8ed8c9ea-7052-4c1d-a4d7-b9c10bffea6f" 


So using that in our query will insure that only account with a value in the Department field in included in our result. Neat, right?

Exclude accounts having a specific AccountName

-AccountName:Prod\B

This will enable you to exclude specific Accounts or groups of accounts like meeting rooms, cars and similar object as the AccountName often indicates which kind of account it is.

 

Search Scope

In this case search scope is defined as the list of fields/properties in the SharePoint User Profile used in the matching. By default we are matching against every field, however this will sometimes cause some rather strange results, espcially if you are not using Ranking.

Example: In this Org we have a department called QA, and would expect the members of that department to show up when doing a search for the query "QA", however Bob from Accounting shows up as number 4 result, ahead of several collegues from the QA department. Why?

Well, after going through Bobs account we can see he is a member of a security group named "Financial QA".......and that is sufficient to mess up the search results.

Of the UPA fields Description, Interests, Memberships and PeopleKeywords can contains values that causes unexpected results.

 

One option that will solve this issue could be to limit your search to only match on a set of specific fields. This will to some extend reduce the general usebility of people search as the end users might not be awere of this limitation.

Often these fields are used in such at limited search: 

FirstName

LastName

PreferredName

Department

PeopleKeywords

WorkEmail

MobilePhone

Location

Responsibilities

PastProjects

MobilePhone

Interests

Description

JobTitle

MobilePhone

Skills


Ranking and sorting

Ranking and sorting decides in which order the search results will be shown. 


Sorting by Name

FirstName

LastName

PreferredName

 

Sorting using XRANK

XRANK specifies a numeric value for each result, usually calculated by Microsoft using the selected Ranking Model. But we are able to tweak this ranking calculation by boosting results that matches a keyword. 

Example:

XRANK(cb=1.5) FirstName:{searchTerms} OR XRANK(cb=0.5) Department:{searchTerms}

In this case we are boosting an account by factor 1.5 (150%) if the query matches FirstName and by 50% if the query matches Department.

Ranking model

In most cases we are using the ”People Search social distance model” ranking model as it is a good allround model for people search.

 

Additional info: Tech and me: People Search ranking for dummies (techmikael.com)

 

Tooling

When working with User profile data and search you should be familiar with these tools:

SharePoint Administation, specificly User Profiles (raw data) and the Search Schema on the tenant level ( mapning fields from UPA to Managed Properties)

SP Query Tool, PnP-Tools/Solutions/SharePoint.Search.QueryTool at master · pnp/PnP-Tools · GitHub, a desktop app that allows you to test both your quiries and your data.

 

SP Editor, a Chrome/Edge extension , GitHub - tavikukko/Chrome-SP-Editor: Extension for creating and updating files (js, css) in SharePoint Online from Developer Tools

Similar to the SP Quiry Tool as far as Search goes, and contains a lot of other SP related features. 


Thursday, April 20, 2023

Surfacing a new User Profile Property in SharePoint Search

 

As part of a Document Management or Intranet project I have often been asked to add a new property to the User Profile Properties. 

Some of the more common purposes are:

Employee Number

Initials

Team (subdivision of Department)


It seems to be a fairly common request as questions about how to enable searching on those new properties occur often in the PnP Modern Search Web Parts GitHub project.



I have used these links as a reference for making a new User Property searchable:

How to create searchable user profile properties in SharePoint Online | RLV Blog (rlvision.com)







Warning: patience is required when working with Search