tag:blogger.com,1999:blog-54399507641760094492024-03-17T06:50:18.261+01:00Tech and meMy musings on Office 365, search, programming and technology.
<br>
(June 1st, 2019, I started as a full time employee of Microsoft, thus any post before that date are solely written on my own behalf)Mikael Svensonhttp://www.blogger.com/profile/04135401463188945665noreply@blogger.comBlogger570125tag:blogger.com,1999:blog-5439950764176009449.post-61734641088652879782024-03-15T10:42:00.000+01:002024-03-15T10:42:31.211+01:00Copilot Productivity Tip – Teams Meeting Insights<strong><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEj90x9EgxJO7wt8jIIMW8_HGNb8Q9ywYoNui8rNOixW5eZ66xP3dyflv7KckctNZSzFl13K-QYoOY3n4ozmwPFadPy3L7Xd8llBhiDCGsb4PGZUHm4eZDkIWsF4NtmwNWACg1-5jnU0Sr7O5Oa_S0hIpR2i64-HPFZN6bNm6A68oOOE9cFVvmxdyetn5ZTk" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="729" data-original-width="765" height="610" src="https://blogger.googleusercontent.com/img/a/AVvXsEj90x9EgxJO7wt8jIIMW8_HGNb8Q9ywYoNui8rNOixW5eZ66xP3dyflv7KckctNZSzFl13K-QYoOY3n4ozmwPFadPy3L7Xd8llBhiDCGsb4PGZUHm4eZDkIWsF4NtmwNWACg1-5jnU0Sr7O5Oa_S0hIpR2i64-HPFZN6bNm6A68oOOE9cFVvmxdyetn5ZTk=w640-h610" width="640" /></a></div><br />Time spent per day before: 0-120 minutes<br /></strong><div><div><strong>Time spent with Copilot: 0-15 minutes</strong></div><div><p><strong>Resources</strong></p> <ul> <li><a href="https://support.microsoft.com/en-au/office/get-started-with-copilot-in-microsoft-teams-meetings-0bf9dd3c-96f7-44e2-8bb8-790bedf066b1" target="_blank">Get started with Copilot in Microsoft Teams meetings</a></li> <li><a href="https://www.youtube.com/watch?v=rLC2frnUasw" target="_blank">Copilot in Teams and Intelligent recap | After the meeting</a> (video)</li> <li><a href="https://www.microsoft.com/en-us/videoplayer/embed/RW1chhn" target="_blank">Copilot in Teams | Catch up on meetings</a> (video)</li> </ul> <p>The beauty of online meetings with transcripts is the ability to quickly go back and find key points later without having to watch the recording or read thru the full transcript. </p> <p>By default Teams provides an AI notes section with a quick summary, and using the Copilot pane you can ask more direct questions such as summarizing your talking points, or ask what your action items were for the meeting.</p> <p>My best example is a late night meeting where I forgot to take notes and the next morning I knew I was supposed to contact an “Andrew”, but had forgotten the full name. Requesting the name in the meetings Copilot quickly gave me the name, saving me around 15 minutes and some grief.</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEim1fH-dpMBYnRep5PPXmyi6QGj5up2Pbi5Bq2KBccgv921XsAXX0u1xr0FDVFsYe80ljKcUe5z7AOrSVJ56mrp60tsoxqYhYos_UVIx5M9v84HYxYYxzBa52rH9D2W_3Qe-9we2nddIe4Nxz61rPLcObZl8VgqE8W05po-Cs4vxjECsi0hw9LAk6ZaS6yn" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="712" data-original-width="1024" height="446" src="https://blogger.googleusercontent.com/img/a/AVvXsEim1fH-dpMBYnRep5PPXmyi6QGj5up2Pbi5Bq2KBccgv921XsAXX0u1xr0FDVFsYe80ljKcUe5z7AOrSVJ56mrp60tsoxqYhYos_UVIx5M9v84HYxYYxzBa52rH9D2W_3Qe-9we2nddIe4Nxz61rPLcObZl8VgqE8W05po-Cs4vxjECsi0hw9LAk6ZaS6yn=w640-h446" width="640" /></a></div><br /><br /><p></p> <br /></div></div>Mikael Svensonhttp://www.blogger.com/profile/04135401463188945665noreply@blogger.comtag:blogger.com,1999:blog-5439950764176009449.post-9607906203873696222024-03-08T17:12:00.001+01:002024-03-15T09:58:17.383+01:00Allowing arbitrary custom scripting in SharePoint Online, or not? – that is the question! (aka Stealing your data since 2001!)<p>…and the answer is, as it always has been, NO!</p> <p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhuuTsflU_GDd0QgZvDUNpcErgKwsUcqDZQSGE00Rtls75CCf-dkqY8O_PoEnatfDf9YNCpeEH0FpdjWMFN8lirMZM4Qm32589IFap_3c0d6QM5pLVxmrS5lkox3wI0fstmpziQiJQF5KB-P2Skk1UW6powxzi11S2-4_NHJ7tYwIoPjfS7fx-Hyfi3gSnc" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="630" data-original-width="1024" height="394" src="https://blogger.googleusercontent.com/img/a/AVvXsEhuuTsflU_GDd0QgZvDUNpcErgKwsUcqDZQSGE00Rtls75CCf-dkqY8O_PoEnatfDf9YNCpeEH0FpdjWMFN8lirMZM4Qm32589IFap_3c0d6QM5pLVxmrS5lkox3wI0fstmpziQiJQF5KB-P2Skk1UW6powxzi11S2-4_NHJ7tYwIoPjfS7fx-Hyfi3gSnc=w640-h394" width="640"></a></div><br><br><p></p> <p><em>Disclaimer: the opinions of this post are mine entirely, and nothing to do with my work at Microsoft. I have not changed opinion on this matter in the past many many years.</em></p> <p>Sparked by the recent message center post <a href="https://admin.microsoft.com/Adminportal/Home?#/MessageCenter/:/messages/MC714186" target="_blank">MC714186 – Remove Custom Script setting in OneDrive and SharePoint web</a>, I figured I’d write out my stance and my full support of the planned change.</p> <blockquote> <p><em>Summary: The Custom Script setting in OneDrive and SharePoint web will be removed in March 2024. A new PowerShell command, "DelayDenyAddAndCustomizePagesEnforcement", has been introduced to delay the change to custom script set on the Tenant until mid-November 2024. The NoScriptSite setting will be configured to True for all existing SharePoint sites and OneDrive sites except for specific site templates. Existing scripts in OneDrive and SharePoint sites will remain unaffected. Administrators can permit the execution of custom scripts on specific SharePoint sites using the Set-SPOSite command.</em></p> </blockquote> <p><strong>In the above summary I want to point out that “existing scripts will remain unaffected” means classic page injections. Not SPFx solutions on with the setting requiresCustomScript=true.</strong></p> <a href="http://www.techmikael.com/2024/03/allowing-arbitrary-custom-scripting-in.html#more">Read more »</a>Mikael Svensonhttp://www.blogger.com/profile/04135401463188945665noreply@blogger.comtag:blogger.com,1999:blog-5439950764176009449.post-67945909089774397502024-01-18T15:34:00.004+01:002024-01-18T15:34:25.356+01:00Easier editing of Microsoft Search verticals in SharePoint sites (finally fixed!)<p>This is perhaps a tiny one, but for the longest time search verticals in a SharePoint site or SharePoint hub site has been a bit of a mystery when you wanted to edit a vertical. To invoke edit, you had to double click the vertical, as there was no Edit button in the ribbon.</p><p>The issue has been known since the feature rolled out, but not addressed. I'll be as blunt to say I decided to take matters into my own hands and just fix it. So here you go, a gift from me to allow a more intuitive way of editing search verticals in SharePoint - as the Microsoft 365 Admin center has had the Edit button always.</p><p>At last the experience matches the documentation at <a href="https://learn.microsoft.com/en-us/microsoftsearch/manage-verticals#manage-site-level-verticals">https://learn.microsoft.com/en-us/microsoftsearch/manage-verticals#manage-site-level-verticals</a>.</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEiqH5yomwXGHvFaGRwnP2zjf2GOTyPdTFDVQRqBYFEtrUchM8_a5vB5us8qguc9JYPANU7uDooqqLLX-y6IKgZGRd8mXKvH6BN9heQ-S-O-1QEu6Uel6K1nBV23Lrn2jAEUXzYo_PmQZ7PyoGygZLfrAW6wXgWTlVpR2ZYGBAQmkPCks3hiTS7uNZlmKpP6" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img alt="" data-original-height="620" data-original-width="995" height="399" src="https://blogger.googleusercontent.com/img/a/AVvXsEiqH5yomwXGHvFaGRwnP2zjf2GOTyPdTFDVQRqBYFEtrUchM8_a5vB5us8qguc9JYPANU7uDooqqLLX-y6IKgZGRd8mXKvH6BN9heQ-S-O-1QEu6Uel6K1nBV23Lrn2jAEUXzYo_PmQZ7PyoGygZLfrAW6wXgWTlVpR2ZYGBAQmkPCks3hiTS7uNZlmKpP6=w640-h399" width="640" /></a></div><br /><br /><p></p>Mikael Svensonhttp://www.blogger.com/profile/04135401463188945665noreply@blogger.comtag:blogger.com,1999:blog-5439950764176009449.post-28366014595943234052024-01-11T12:49:00.033+01:002024-01-11T14:51:33.988+01:00Demystifying Author properties on files in SharePoint and search<p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtQQWpH6Cl5IXE4i-eZ83sdkZ32IO3p6lzixRfGYDxHWZ8eyQ_go4vPkWi0qTIDmqYIeTKPT60_Y8Rqp0Xn1mFygPJx1oZpYkdnN3gmXU53itTEKxMldMg1Xqw6rP8Zo_mHywkTe2410PneYLtVZ9w85sC6EwE0w1zWFyD7nvxZ23imfE0bPpoDSGUg6bl/s512/demystify.jpg"><img alt="demystify" border="0" height="516" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtQQWpH6Cl5IXE4i-eZ83sdkZ32IO3p6lzixRfGYDxHWZ8eyQ_go4vPkWi0qTIDmqYIeTKPT60_Y8Rqp0Xn1mFygPJx1oZpYkdnN3gmXU53itTEKxMldMg1Xqw6rP8Zo_mHywkTe2410PneYLtVZ9w85sC6EwE0w1zWFyD7nvxZ23imfE0bPpoDSGUg6bl/s512/demystify.jpg" style="background-image: none; display: inline;" title="demystify" width="516"></a></p><p>For as long as I have been doing SharePoint, figuring out what properties to use when filtering or displaying search results in regards to people has been a challenge as the documentation in this space is somewhat lacking. I’m not sure why I haven’t done this writeup earlier, but no time like the present.</p> <a href="http://www.techmikael.com/2024/01/demystifying-author-properties-on-files.html#more">Read more »</a>Mikael Svensonhttp://www.blogger.com/profile/04135401463188945665noreply@blogger.comtag:blogger.com,1999:blog-5439950764176009449.post-8083190078344526512023-12-08T13:40:00.003+01:002024-01-12T09:34:37.735+01:00AI model bias and why responsible technology matters – exemplified by image generation<p>In this era of AI where ChatGPT with LLM’s has become the hottest topic in computer science since the Apple Macintosh and the IBM PC, I figured I’d do a small write-up on AI model bias and why paying attention to bias is important. This is especially true when it comes to enterprise scenarios where Microsoft is launching a long range of AI powered copilot experiences.</p> <blockquote> <p><em>The author of this article works for Microsoft (December 2023) and is an internal champion for responsible ai and technology as well as internal champion for privacy and compliance.</em></p> </blockquote> <p>At Microsoft we have a high bar for delivering responsible AI solutions, which means there is a lot of work put in place to ensure the output from AI systems follow Microsoft’s AI principles to be fair, inclusive, reliable and safe, privacy and security is accounted for, and the systems are accountable.</p> <p>Any model, that be a large language model (LLM) or a model to generate image will inherently have bias built in due to the training data used. In smaller models you can manually verify the training data to counter some bias and balance the training set, but as models grow large this becomes inherently harder. I’m not saying there are not systems in place to counter training bias already, but to truly counter bias this has to be built into pre and post processing of input prompts and outputs from the models.</p> <p>I will use image generation as an example where I will show the difference between using image creator in Microsoft Designer (<a href="https://designer.microsoft.com/" title="https://designer.microsoft.com/">https://designer.microsoft.com/</a>) built on DALL·E 3 from OpenAI and Stable Diffusion XL, which is an open source model from Stability.AI (<a href="https://stability.ai/" title="https://stability.ai/">https://stability.ai/</a>). The Microsoft solution has guardrails in place, where the open source solution do not – unless you add them yourself via prompting. Not saying neither of them are perfect as examples will show.</p> <p>I want to call out that any bias shown is not statistically verified, and only based on generating a set of sample random images with the same prompt.</p> <h4>Example 1 - photo of correctional officer in a well lit hallway eating a donut</h4> <a href="https://lh3.googleusercontent.com/u/0/d/1vuxrBpF78lxuzhffvHgeDx169EX68UO9"><img alt="image" border="0" height="323" src="https://lh3.googleusercontent.com/u/0/d/18qEyIRngpAC2o7TNlaFgz8aPylu1b_a0" style="background-image: none; display: inline;" title="image" width="644" /></a> <p>The above eight images are from DALL·E 3. They are all close-up photos showing a fit, light skinned male with dark hair.</p> <a href="https://lh3.googleusercontent.com/u/0/d/1Y_r00wOeM5XTIJA8YulC7yAj3UsowGOs"><img alt="image" border="0" height="328" src="https://lh3.googleusercontent.com/u/0/d/1FH2qlAOd_lCvnYYuE7HiYq3LfK2A71nc" style="background-image: none; display: inline;" title="image" width="644" /></a> <p>In comparison the SDXL images have a wider focal point showing the full body. It’s a mix of male and female people, and also a mix of light and dark skinned people. I would argue the SDXL model is more accurate to what people look like in 2023, while the DALL·E 3 model output “perfect” looking people. If this is due to the images the models are trained on, or the prompt being augmenting to have “perfect” looking people I do not know. </p> <p>The default color palette is also different where DALL·E 3 has more green and SDXL has more brownish colors.</p> <p>If I add “overweight” to the DALL·E 3 prompt, the Responsible AI filter kicks in and blocks the generation. If I add “fat”, then it works. <br /></p> <p><a href="https://lh3.googleusercontent.com/u/0/d/1Pp9SuNr2fJKVHEU098DAjbNQd0d9Cios"><img alt="image" border="0" height="241" src="https://lh3.googleusercontent.com/u/0/d/17vxV81QHb4THRrh6Rr4CwmLOaeGJ7UsV" style="background-image: none; display: inline; margin: 0px;" title="image" width="244" /></a></p> <p>With SDXL I can modify the prompt to <em>“<strong>closeup</strong> photo of a <strong>slim white male</strong> correctional officer in a well lit hallway eating a donut”</em> to mimic what DALL·E 3 output by default – to counter the wide angle and real life looking people bias of the model.</p> <p><a href="https://lh3.googleusercontent.com/u/0/d/1RvUOfm1MufcJyhlEXpPyLMaMLFpz1r8V"><img alt="image" border="0" height="243" src="https://lh3.googleusercontent.com/u/0/d/1jVFsp6AJsRwVtBO5bGAhZaoO5hbOrgte" style="background-image: none; display: inline; margin: 0px;" title="image" width="244" /></a></p> <h4>Example 2 – woman</h4> <p>Let’s try a simple prompt with the subject “woman”. For SDXL I added negative prompting to avoid any nsfw images – which is blocked as part of DALL·E 3 RAI principles.</p> <a href="https://lh3.googleusercontent.com/u/0/d/1IFObD1h2va9w9UVRgqtwBsNVJIhE7k0u"><img alt="image" border="0" height="339" src="https://lh3.googleusercontent.com/u/0/d/1Fh45_Oa4dBUH1Beg7nAnKOpD0CkyIW8m" style="background-image: none; display: inline;" title="image" width="644" /></a> <p>DALL·E 3 seems to pivot towards portrait photo’s when no extra contextual information is given, as that is likely the intent with a simple input subject. They are also all dark haired and seem to be young women.</p> <a href="https://lh3.googleusercontent.com/u/0/d/1LzjrFGHpjl6VMUToAvhD7Gfxa7IQSdbO"><img alt="image" border="0" height="329" src="https://lh3.googleusercontent.com/u/0/d/1flZufK0A0eCoB6e42mbjEGaBhlC8_ENb" style="background-image: none; display: inline;" title="image" width="644" /></a> <p>In comparison SDXL gives a wide variety of image types, pivoting to more art-like images instead of photos.</p> <h4>Example 3 – painting of a beautiful norwegian fjord with vikings, with a boing 737 in the sky, in the style of munch’s scream</h4> <a href="https://lh3.googleusercontent.com/u/0/d/1-prdX8utWW5ZZ7uH3vYxFXHGkAjmCLd3"><img alt="image" border="0" height="239" src="https://lh3.googleusercontent.com/u/0/d/1aEPXGEs5SJERbs56Om6d9rlEdvlm1fkJ" style="background-image: none; display: inline; margin: 0px;" title="image" width="244" /></a> <p>The DALL·E 3 painting nails the airplane and pretty much the painting style of Edward Munch.</p> <a href="https://lh3.googleusercontent.com/u/0/d/1pkdY39Ksbhek04Sm7bbVh_qnm2PtR5Rl"><img alt="image" border="0" height="243" src="https://lh3.googleusercontent.com/u/0/d/1Mei_y41s5arRQG_AZcz30b3U4EGXvZEt" style="background-image: none; display: inline; margin: 0px;" title="image" width="244" /></a> <p>The SDXL one is not bad either, but the Munch style is not as visible for this one sample. And the scale of the plane vs. the viking ship and buildings is way off. </p> <h4>Learnings</h4> <p>These simple examples shows that articulating your intent in prompting is crucial. Either the system has to add guardrails and contextual information to the prompt, or the person prompting has to be articulate on what they want returned and what they do not want returned. And you have to generate many images to find that ONE you really like.</p> <p>For online services like Microsoft Designer going the safe route is the only approach as people using the service comes from a wide variety of backgrounds and age groups. Taking that extra measure to ensure everyone feels safe is important to trusting the service.</p> <p>Open source solutions you can run on your own PC/phone/table can allow for less guardrails as the individual running it likely has more skill and is using the tool themselves. Maybe the analogy of hiring a carpenter as a service vs. hammering yourself can be used. You trust a hired professional to meet a certain bar, while you are responsible yourself on anything you do.</p> <p>When it comes LLM’s we know they are largely based on English text today, and would favor input and output in this language. As they are built on public data, that will influence default writing style as well. fortunately ChatGPT and Microsoft Copilots put a lot of effort into the system prompts put around the user prompt, to counter any bias in the model. This is to ensure grounding in facts and avoid hallucinations. More on that for another post.</p> <h4>References</h4> <p>I used the service of <a href="https://designer.microsoft.com/image-creator" title="https://designer.microsoft.com/image-creator">https://designer.microsoft.com/image-creator</a> to create the DALL·E 3 images, and I used the <a href="https://apps.apple.com/us/app/draw-things-ai-generation/id6444050820" target="_blank">Draw Things app</a> on a MacBook with an 8-bit quantized version of the default SDXL model. The Draw Things app also work on iOS devices.</p>Mikael Svensonhttp://www.blogger.com/profile/04135401463188945665noreply@blogger.comtag:blogger.com,1999:blog-5439950764176009449.post-67962768410212540352023-08-10T12:29:00.006+02:002023-08-10T12:29:59.942+02:00How to paginate large results sets for SharePoint items using the Microsoft Graph Search API<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjo_T4_7fmuPo9AwHjj1N7RW97HVEBS-C-OldCzTSyWr9cVPG5dGU4_MqN2rEKbiuXfqbIrxySusLuPSXpjFhUXIpFc5ixA6xCxXhcCs1DsDUIybIpyr6IWRTSzv8fvNJeziEAx73FoIhyZI5lKg8rae97g2pqK_573HYTL6-FUjNN3AuJvh38JB4RqDhqE/s1024/_low_poly__many_documents_and_folders_swirling_around_in_the_air_with_large_numerics_speeding_by__office_space__people_working_2455214634.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="512" data-original-width="1024" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjo_T4_7fmuPo9AwHjj1N7RW97HVEBS-C-OldCzTSyWr9cVPG5dGU4_MqN2rEKbiuXfqbIrxySusLuPSXpjFhUXIpFc5ixA6xCxXhcCs1DsDUIybIpyr6IWRTSzv8fvNJeziEAx73FoIhyZI5lKg8rae97g2pqK_573HYTL6-FUjNN3AuJvh38JB4RqDhqE/w640-h320/_low_poly__many_documents_and_folders_swirling_around_in_the_air_with_large_numerics_speeding_by__office_space__people_working_2455214634.png" width="640" /></a>
<p style="clear: both;">If you want to paginate over a large set of results for some reason using the Microsoft Graph Search API, you can employ the logic mentioned for the SharePoint API at <a href="https://learn.microsoft.com/en-us/sharepoint/dev/general-development/pagination-for-large-result-sets" style="text-align: left;">https://learn.microsoft.com/en-us/sharepoint/dev/general-development/pagination-for-large-result-sets</a><span style="text-align: left;">. Note that this option applies to OneDrive and SharePoint items, not necessarily other content sources available via the Graph Search API (not tested).</span></p><p>Use a basic JSON template like below for your search requests, or modify to add other parameters needed for your request.</p><div style="background-color: #fffffe; font-family: Menlo, Monaco, "Courier New", monospace; font-size: 12px; line-height: 18px; white-space: pre;"><div>{</div><div> <span style="color: #a31515;">"requests"</span>: [</div><div> {</div><div> <span style="color: #a31515;">"entityTypes"</span>: [</div><div> <span style="color: #0451a5;">"driveItem"</span></div><div> ],</div><div> <span style="color: #a31515;">"from"</span>: <span style="color: #098658;">0</span>,</div><div> <span style="color: #a31515;">"size"</span>: 5<span style="color: #098658;">00</span>,</div><div> <span style="color: #a31515;">"query"</span>: {</div><div> <span style="color: #a31515;">"queryString"</span>: <span style="color: #0451a5;">"contoso indexdocid>**LASTID**"</span></div><div> },</div><div> <span style="color: #a31515;">"fields"</span>: [</div><div> <span style="color: #0451a5;">"indexdocid"</span></div><div> ],</div><div> <span style="color: #a31515;">"sortProperties"</span>: [</div><div> {</div><div> <span style="color: #a31515;">"name"</span>: <span style="color: #0451a5;">"[DocId]"</span>,</div><div> <span style="color: #a31515;">"isDescending"</span>: <span style="color: #0451a5;">"false"</span></div><div> }</div><div> ]</div><div> }</div><div> ]</div><div>}</div><div><br /></div><div><span style="font-family: Times; font-size: medium; white-space: normal;">Where <b>**LASTID**</b> is 0 on the initial request. Once you get results back, pick the value of indexdocid of the last result, and use that as <b>**LASTID*</b>* on the next request. In the below screenshot you would use 2377359 for the seconds request. Continue this logic until you stop getting results, and you should have iterated all files (driveItems) containing the term <b>contoso</b> for the above sample.<br /><br /></span></div><div><span style="font-family: Times; font-size: medium; white-space: normal;"><br /></span></div><div><span style="font-family: Times; font-size: medium; white-space: normal;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhdpe9qKrkp6SOcI1oJZvCH85bXQoFKGJIKq5n25MmHlexFETV9nBXIZOvFAsHkWp9TUW0LmDsXw4s3JeiSd0VhsD_tasMy6GV8wDrvBUGBJlAH9mtLbsEkNhMbYX4kOv8c0JLsKvCUOyo8u2mXUu0265FFItz2HyQoSfXPczzsolZA_4IgRbbLHg4s9emy" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img alt="" data-original-height="434" data-original-width="1320" height="210" src="https://blogger.googleusercontent.com/img/a/AVvXsEhdpe9qKrkp6SOcI1oJZvCH85bXQoFKGJIKq5n25MmHlexFETV9nBXIZOvFAsHkWp9TUW0LmDsXw4s3JeiSd0VhsD_tasMy6GV8wDrvBUGBJlAH9mtLbsEkNhMbYX4kOv8c0JLsKvCUOyo8u2mXUu0265FFItz2HyQoSfXPczzsolZA_4IgRbbLHg4s9emy=w640-h210" width="640" /></a></div><br /><br /></span></div></div><p></p>Mikael Svensonhttp://www.blogger.com/profile/04135401463188945665noreply@blogger.comtag:blogger.com,1999:blog-5439950764176009449.post-46234892493126022332023-07-03T15:04:00.000+02:002023-07-03T15:04:05.799+02:00MacBook Pro M1 with 4K monitors on a ThinkPad USB-C dock<p>I have a couple of 4K monitors at work via a ThinkPad dock. If I were running the native resolution of 3840x2160 pixels the fonts and icons were just too small for my aging eyes. The alternative native resolution was 1980x1080, and then things get too large.</p><p>The ideal for me is scaling to 2560x1440. Sure you can do this via the display system settings, but then everything is blurry. But there is a fix.</p><p></p><ol style="text-align: left;"><li>Install DisplayLink Manager from <a href="https://www.synaptics.com/products/displaylink-graphics/downloads/macos">https://www.synaptics.com/products/displaylink-graphics/downloads/macos</a> </li><li>Check the experimental mode for 3008x and 2560x modes support<br /><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhKveFlO14MsDqY96rN9GL99TTFXHbdZYi2HWWRE76xUdQgzdsF15-C9HsAtYyDAk63BYc6bXrNW2kCcJEEQy-vvZLujwqLKrsVT8qQl6z6oK98zcmkKNSoh0iC85cHsqKefrgy0Kg1FqqQ9J86RC6xc9BhrlwtiVRilN4SPG6_c6a5u9idD0Zncs3GHPO2"><img alt="" data-original-height="636" data-original-width="1378" height="199" src="https://blogger.googleusercontent.com/img/a/AVvXsEhKveFlO14MsDqY96rN9GL99TTFXHbdZYi2HWWRE76xUdQgzdsF15-C9HsAtYyDAk63BYc6bXrNW2kCcJEEQy-vvZLujwqLKrsVT8qQl6z6oK98zcmkKNSoh0iC85cHsqKefrgy0Kg1FqqQ9J86RC6xc9BhrlwtiVRilN4SPG6_c6a5u9idD0Zncs3GHPO2=w430-h199" width="430" /></a></li><li>Then pick scaled text in Display settings, getting you a nativ scaled 2560x1440 which is not blurry in HiDPI mode. See <a href="https://support.displaylink.com/knowledgebase/articles/1993915">https://support.displaylink.com/knowledgebase/articles/1993915</a>.<br /><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhHvr2HE6Feyo7dHnLgMZd-O1J-4cE79fhfsB7Ap_l4mbNCm3n78WRljv0UoDdfyMrBFTNN2pXLnJyYS7knvJH97CPcBhRlha9mtXlHRh8vch-aKkVUXf7vjt_c_XWiorHhF-mHDKpf8W0YUjQySp4RgyfzFTALuFp9XaKPN-H_lMFKZWRF3GvtVx5nCDHK"><img alt="" data-original-height="750" data-original-width="958" height="240" src="https://blogger.googleusercontent.com/img/a/AVvXsEhHvr2HE6Feyo7dHnLgMZd-O1J-4cE79fhfsB7Ap_l4mbNCm3n78WRljv0UoDdfyMrBFTNN2pXLnJyYS7knvJH97CPcBhRlha9mtXlHRh8vch-aKkVUXf7vjt_c_XWiorHhF-mHDKpf8W0YUjQySp4RgyfzFTALuFp9XaKPN-H_lMFKZWRF3GvtVx5nCDHK" width="307" /></a></li></ol><p></p>Mikael Svensonhttp://www.blogger.com/profile/04135401463188945665noreply@blogger.comtag:blogger.com,1999:blog-5439950764176009449.post-17053405577419592102023-04-25T15:39:00.000+02:002023-04-25T15:39:13.224+02:00New useful managed properties to use in Microsoft Search<a href="https://drive.google.com/uc?id=1ywLfq9mA5UbhtujUoXrtXYTZKy464_Th"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://drive.google.com/uc?id=1VTqHU1S1sWYLZxo7Wg6cTVvkVJXKoLUN" width="644" height="484" /></a> <p>For those working with hub sites in SharePoint you have for a long time used the managed property <strong>DepartmentId</strong>, later accompanied by <strong>RelatedHubSites</strong> when hub site hierarchies was enabled.</p> <p>Now the time has come to have these properties, and some more, added to the public documentation.</p> <p>Take a peek at <a title="https://learn.microsoft.com/en-us/sharepoint/crawled-and-managed-properties-overview" href="https://learn.microsoft.com/en-us/sharepoint/crawled-and-managed-properties-overview" target="_blank">https://learn.microsoft.com/en-us/sharepoint/crawled-and-managed-properties-overview</a> which covers these new properties available for online experiences.</p> <p>The documentation UX is not ideal, so ensure you scroll the table of properties to the right to read the comments per property. Here’s a copy of the table for reference where I moved the comment for visibility.</p> <p>Note the (*) highlighting that it’s not guaranteed that each item has a value in the property.</p> <table cellspacing="0" cellpadding="0" border="1"><tbody> <tr> <td valign="top"> <p><b>Property name</b></p> </td> <td valign="top"> <p><b>Type</b></p> </td> <td valign="top"> <p><b>Comment</b></p> </td> <td valign="top"> <p><b>Multi-valued</b></p> </td> <td valign="top"> <p><b>Queryable</b></p> </td> <td valign="top"> <p><b>Searchable</b></p> </td> <td valign="top"> <p><b>Retrievable</b></p> </td> <td valign="top"> <p><b>Refinable</b></p> </td> <td valign="top"> <p><b>Sortable</b></p> </td> <td valign="top"> <p><b>Mapped crawled properties</b></p> </td> </tr> <tr> <td valign="top"> <p>DepartmentId</p> </td> <td valign="top"> <p>Text</p> </td> <td valign="top"> <p>Site ID of the hub of the immediate hub. Applies to all items in the hub/associated sites.</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> <p>Yes</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> <p>Yes</p> </td> <td valign="top"> <p>Yes</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> <p>ows_DepartmentId</p> </td> </tr> <tr> <td valign="top"> <p>RelatedHubSites</p> </td> <td valign="top"> <p>Text</p> </td> <td valign="top"> <p>Site IDs of associated hubs including hub hierarchies. Can be used instead of DepartmentId for most scenarios. Applies to all items in the hub/associated sites.</p> </td> <td valign="top"> <p>Yes</p> </td> <td valign="top"> <p>Yes</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> <p>Yes</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> <p>ows_RelatedHubSites</p> </td> </tr> <tr> <td valign="top"> <p>IsHubSite</p> </td> <td valign="top"> <p>Yes/No</p> </td> <td valign="top"> <p>Applies to the site result of a hub (contentclass=STS_Site)</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> <p>Yes</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> <p>Yes</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> <p>ows_IsHubSite</p> </td> </tr> <tr> <td valign="top"> <p>ModifierAADIDs</p> </td> <td valign="top"> <p>Text</p> </td> <td valign="top"> <p>Semi-colon separated list of AADIDs for modifiers of a file or page ordered in date descending order. (*)</p> </td> <td valign="top"> <p>Yes</p> </td> <td valign="top"> <p>Yes</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> <p>Yes</p> </td> <td valign="top"> <p>Yes</p> </td> <td valign="top"> <p>Yes</p> </td> <td valign="top"> </td> </tr> <tr> <td valign="top"> <p>ModifierDates</p> </td> <td valign="top"> <p>Date and Time</p> </td> <td valign="top"> <p>Semi-colon separated list of modification dates for modifiers of a file or page ordered in date descending order. (*)</p> </td> <td valign="top"> <p>Yes</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> <p>Yes</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> </td> </tr> <tr> <td valign="top"> <p>ModifierNames</p> </td> <td valign="top"> <p>Text</p> </td> <td valign="top"> <p>Semi-colon separated list of the names for modifiers of a file or page ordered in date descending order. (*)</p> </td> <td valign="top"> <p>Yes</p> </td> <td valign="top"> <p>Yes</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> <p>Yes</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> </td> </tr> <tr> <td valign="top"> <p>ModifierUPNs</p> </td> <td valign="top"> <p>Text</p> </td> <td valign="top"> <p>Semi-colon separated list of UPNs for modifiers of a file or page ordered in date descending order. (*)</p> </td> <td valign="top"> <p>Yes</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> <p>Yes</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> </td> </tr> <tr> <td valign="top"> <p>ChapterTitle</p> </td> <td valign="top"> <p>Text</p> </td> <td valign="top"> <p>Semi-colon separated list of <a href="https://support.microsoft.com/en-us/office/auto-generated-chapters-on-teams-meeting-videos-7af781d3-ed33-4aae-bb66-0abd4c6c4c98" target="_blank">auto-generated chapters on Teams meeting videos</a>. (*)</p> </td> <td valign="top"> <p>Yes</p> </td> <td valign="top"> <p>Yes</p> </td> <td valign="top"> <p>Yes</p> </td> <td valign="top"> <p>Yes</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> <p>ChapterTitle</p> </td> </tr> <tr> <td valign="top"> <p>ChapterOffset</p> </td> <td valign="top"> <p>Text</p> </td> <td valign="top"> <p>Semi-colon separated list of time codes matching the chapter titles for <a href="https://support.microsoft.com/office/auto-generated-chapters-on-teams-meeting-videos-7af781d3-ed33-4aae-bb66-0abd4c6c4c98" target="_blank">auto-generated chapters on Teams meeting videos</a>. (*)</p> </td> <td valign="top"> <p>Yes</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> <p>Yes</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> <p>No</p> </td> <td valign="top"> <p>ChapterOffset</p> </td> </tr> </tbody></table> <p>* Property is not guaranteed to contain data.</p>Mikael Svensonhttp://www.blogger.com/profile/04135401463188945665noreply@blogger.comtag:blogger.com,1999:blog-5439950764176009449.post-53750997117595995232023-04-25T14:57:00.001+02:002023-04-25T14:57:46.679+02:00Retirement of Dynamic Ordering feature in classic search experiences<p>In <a href="https://admin.microsoft.com/Adminportal/Home?ref=MessageCenter/:/messages/MC544789" target="_blank">MC44789</a> post from April 22nd, 2023, Microsoft announced the retirement of the dynamic ordering feature experience in classic search.</p> <p>If you don’t know what the feature is, the below image highlights the feature seen in the query builder in classic search result sources, query rules and search web parts.</p> <a href="https://drive.google.com/uc?id=10LatGirpJaCOg_GBQ2W_TkEoe9F7xHom"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://drive.google.com/uc?id=188CyYW2J0NlLBAAPOXMVEaGBG6svSk98" width="644" height="271" /></a> <p>The above screenshot show a rule which if it matches the term <strong>xrank</strong> in the title results will be boosted to the top of the result list.</p> <p>Wait what?? So I will no longer be able to boost items per my own logic? Sure you can, and this is called out in the MC post – <em><strong>“Functional parity may be achieved by adding XRANK clauses directly to the query template in the Query Builder dialog.”</strong></em></p> <p>Previously when testing the query from the test tab you could see the output of the final query. However this is no longer the case and I’ll teach you how to transition dynamic rules over to manual XRANK.</p> <a href="https://drive.google.com/uc?id=1FmsuIIT3AzQamy2r7PTDrrOPjyJgQuWf"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://drive.google.com/uc?id=1Gs1aR698mRO6M4abaDgBggEkyFUDhJfN" width="615" height="416" /></a> <p>Today using the constant boost, or cb, parameter to rank is not the recommended approach. The reason is that the internal rank scale has changed over the years so the value 5,000 may or may not be required to move something to the top. The below example has a rank of –17921 so adding 5000 would not help.</p> <a href="https://drive.google.com/uc?id=1_Kv_e1QZj3zl5NbDM4Q5fNPy-i1IlFY9"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://drive.google.com/uc?id=1VyJDKs1oWDUJO9Ktui2idl8sIRD5HdRr" width="644" height="334" /></a> <p>The recommended parameter to use today is to use standard deviation boost with the stdb parameter.</p> <p> <p><em>See <a title="https://learn.microsoft.com/en-us/graph/search-concept-xrank" href="https://learn.microsoft.com/en-us/graph/search-concept-xrank" target="_blank">https://learn.microsoft.com/en-us/graph/search-concept-xrank</a> or </em><a title="https://learn.microsoft.com/en-us/sharepoint/dev/general-development/keyword-query-language-kql-syntax-reference#dynamic-ranking-operator" href="https://learn.microsoft.com/en-us/sharepoint/dev/general-development/keyword-query-language-kql-syntax-reference#dynamic-ranking-operator" target="_blank">https://learn.microsoft.com/en-us/sharepoint/dev/general-development/keyword-query-language-kql-syntax-reference#dynamic-ranking-operator</a><em></em><em> for all parameters.</em></p> <h3>Manually writing dynamic ordering rules as XRANK</h3> <p>A query temple to boost a result to the top can then look like:</p> <p><strong>{?{searchTerms} XRANK(stdb=100) Title:xrank}</strong></p> <p>Feel free to replace 100 with a smaller or larger number as needed.</p> <p>If you want to boost items with <em>title=foo</em> pretty high, and less with <em>title=bar</em> you can use a nested XRANK statement, similar to what multiple dynamic ordering rules will accomplish.</p> <p><strong>{?({searchTerms} XRANK(stdb=5) Title:foo) XRANK(stdb=2) Title:bar}</strong> <p>If you want to demote results instead of promoting them, use a negative number.</p> <p>If you go for decimals instead of integers, I recommend reading <a title="https://www.techmikael.com/2014/11/you-should-use-exponential-notation.html" href="https://www.techmikael.com/2014/11/you-should-use-exponential-notation.html">https://www.techmikael.com/2014/11/you-should-use-exponential-notation.html</a> to ensure they always work.</p></p></p>Mikael Svensonhttp://www.blogger.com/profile/04135401463188945665noreply@blogger.comtag:blogger.com,1999:blog-5439950764176009449.post-29522062257656803722023-04-25T13:20:00.003+02:002023-08-08T13:26:37.734+02:00Filter on managed properties in search with or without values<p>Back in 2014 I wrote the post <a href="https://www.techmikael.com/2014/08/how-to-search-up-items-which-dont-have.html" target="_blank">How To: Search up items which don’t have a value set</a>, which covers how to write keyword query syntax (KQL) filters to return or restrict items depending on if a specific managed property has a value or not. Recently Microsoft added support to more easily query if managed properties of type <strong>Text</strong> contain or does not contain a value.</p> <p>Here’s a link to the updated documentation: </p> <p><a href="https://learn.microsoft.com/en-us/sharepoint/dev/general-development/keyword-query-language-kql-syntax-reference#filter-on-items-where-a-text-property-is-empty-or-contains-a-value" target="_blank" title="https://learn.microsoft.com/en-us/sharepoint/dev/general-development/keyword-query-language-kql-syntax-reference#filter-on-items-where-a-property-is-empty-or-contains-a-value">https://learn.microsoft.com/en-us/sharepoint/dev/general-development/keyword-query-language-kql-syntax-reference#filter-on-items-where-a-text-property-is-empty-or-contains-a-value</a></p> <p><em>Note: The new supported syntax only works for Microsoft 365 / Online</em></p> <a href="https://drive.google.com/uc?id=14uNHYBqRKA8vmKW7MY2QbqY1o7Y62obk"><img alt="image" border="0" height="644" src="https://drive.google.com/uc?id=14yqo9t-Tc7rODkihQkhrEvSxTNGh2MF1" style="background-image: none; display: inline;" title="image" width="644" /></a> <p> </p> <h3>Items missing or having a text value</h3> <p>The syntax is as follows:</p> <strong></strong><table border="1" cellpadding="2" cellspacing="0"><tbody> <tr> <td valign="top"><strong>KQL Syntax</strong></td> <td valign="top"><strong>Description</strong></td> </tr> <tr> <td valign="top">NOT <Property Name>:*</td> <td valign="top">Items where a property does not have a value</td> </tr> <tr> <td valign="top"><Property Name>:*</td> <td valign="top">Items where a property does has a value</td> </tr> </tbody></table> <p>The documentation uses the following example to list SharePoint sites associated to a hub site.</p> <p>(<strong>DepartmentId:* OR RelatedHubSites:*</strong>) AND contentclass:sts_site NOT IsHubSite:true</p> <p>Deciphering the query:</p> <strong></strong><table border="1" cellpadding="2" cellspacing="0"><tbody> <tr> <td valign="top"><strong>KQL</strong></td> <td valign="top"><strong>Description</strong></td> </tr> <tr> <td valign="top">(DepartmentId:* OR RelatedHubSites:*)</td> <td valign="top">return items which has a value in the original DepartmentId managed property or in the successor RelatedHubSites property</td> </tr> <tr> <td valign="top">contentclass:sts_site</td> <td valign="top">return only site items</td> </tr> <tr> <td valign="top">NOT IsHubSite:true</td> <td valign="top">exclude hub site results</td> </tr> </tbody></table> <p>Note that hubs connected to another hub will not be included in the above query. If you want those, then remove the <strong>NOT IsHubSite:true</strong> part and post-process the results as needed.</p> <p>For completeness let’s cover how to accomplish the same for other types of managed properties.</p> <h3>Items missing or having a YesNo value</h3> <p>To find items missing a value in a date property the syntax shown in my 2014 seems to no longer work and should be replaced with the following where the date is some low non-used date.</p> <strong></strong><table border="1" cellpadding="2" cellspacing="0"><tbody> <tr> <td valign="top"><strong>KQL</strong></td> <td valign="top"><strong>Description</strong></td> </tr> <tr> <td valign="top">NOT (RefinableYesNo00:true OR RefinableYesNo00:false)</td> <td valign="top">return items not having a value in a YesNo property</td> </tr> <tr> <td valign="top">(RefinableYesNo00:true OR RefinableYesNo00:false)</td> <td valign="top">return items having a value in a YesNo property</td> </tr> </tbody></table> <h3> </h3> <h3>Items missing or having a date value</h3> <p>To find items missing a value in a date property the syntax shown in my 2014 seems to no longer work and should be replaced with the following where the date is some low non-used date.</p> <strong></strong><table border="1" cellpadding="2" cellspacing="0"><tbody> <tr> <td valign="top"><strong>KQL</strong></td> <td valign="top"><strong>Description</strong></td> </tr> <tr> <td valign="top">NOT RefinableDate00>1900-01-01</td> <td valign="top">return items not having a value in a date property</td> </tr> <tr> <td valign="top">RefinableDate00>1900-01-01</td> <td valign="top">return items having a value in a date property</td> </tr> </tbody></table> <h3> </h3> <h3>Items missing or having a number value</h3> <p>For number type managed properties it’s easier as you typically know the range of values.</p> <strong></strong><table border="1" cellpadding="2" cellspacing="0"><tbody> <tr> <td valign="top"><strong>KQL</strong></td> <td valign="top"><strong>Description</strong></td> </tr> <tr> <td valign="top">NOT Size>=0 </td> <td valign="top">if the managed property only contain positive values, then this will return all items with no value set</td> </tr> <tr> <td valign="top">NOT RefinableDecimal00>=0 NOT RefinableDecimal00<0</td> <td valign="top">return items where the property RefinableDecimal00 has no value</td> </tr> <tr> <td valign="top">Size>=0</td> <td valign="top">return all items having a value which is greater than your smallest value</td> </tr> </tbody></table>Mikael Svensonhttp://www.blogger.com/profile/04135401463188945665noreply@blogger.comtag:blogger.com,1999:blog-5439950764176009449.post-29469271051207442752023-04-07T16:22:00.001+02:002023-04-07T16:22:40.501+02:00There are still new things to learn from the SharePoint Search API I won't share. I will NOT!<p>…I will, just a tad bit late :)</p> <p><a href="https://twitter.com/mikaelsvenson/status/1583384288367501312" target="_blank">This was a tweet I made Friday October 21st</a> once I understood the root cause of an API issue which has popped up in the last months. The issue affected PnP Modern Search web parts when query rules were enabled, and also the Search Query Tool with default settings.</p> <p>I thought it was a weird API issue which had been introduced as part of an ongoing service upgrade for Microsoft Search lately, but turns out everything was working as expected – except the expected part hasn’t been expected for the past many years. And a big thank you to engineers at Microsoft helping me understand what the root cause is.</p> <p>On the API side it manifests itself as follows with the following simple API REST query executed in the SharePoint Search Query Tool where you only get 2 main results where you would expect 10.</p> <p><a title="https://techmikael.sharepoint.com/_api/search/query?querytext='mikael'&enablequeryrules=true&enableinterleaving=true&rowlimit=10&clienttype='ContentSearchHigh'&properties='EnableMultiGeoSearch2:true'" href="https://tenant.sharepoint.com/_api/search/query?querytext='mikael'&rowlimit=10">https://tenant.sharepoint.com/_api/search/query?querytext='mikael'&rowlimit=10</a></p> <a href="https://drive.google.com/uc?id=1Lk1CGz7GcbbgkgjFavcVh_mwqSENRw-J"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://drive.google.com/uc?id=1jLmZzuqlyr0nC2PA38Qjz7TBelkHFyRg" width="644" height="327" /></a> <p>Where are the rest of my 10 results? Well, they happen to be located in the Secondary Results, a place I never looked.</p> <a href="https://drive.google.com/uc?id=1SZGeuhFcato0XsyqqzfJQtidnsLaV4OB"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://drive.google.com/uc?id=1CwPSG-HhCDVwG5uGfkDTA-WwVgOh7bco" width="542" height="484" /></a> <p>I’ll explain the behavior, and it is actually correct (sort of), and I will explain why this happens now in 2022.</p> <h3>A trip down memory lane</h3> <p>When SharePoint 2013 was released Microsoft released the feature of query rules, which allowed to bring in result blocks into the search results as seen below.</p> <p>The below screenshot triggers the rule “People Name in SharePoint” which bring in two result blocks.</p> <p><a href="https://drive.google.com/uc?id=14aUv5qJ9VTRnOoLP1WtGsGNaK0_Tirk6"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://drive.google.com/uc?id=1DVsQ_qhLY2AxgCyQDMxktpPQFF4QB7jx" width="644" height="704" /></a></p> <p>And the query rule definition</p> <p><a href="https://drive.google.com/uc?id=1OP6oHrpAjVEQe88_s4HaUUAF0yDd13Ei"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://drive.google.com/uc?id=1mIMyjZUeKiF4Am4_93wsvUK0g-5dg6MD" width="644" height="403" /></a></p> <p>The definition above says to always place people on top, and possible show documents authored by the person as a block within the results, or interleaved.</p> <p>The thing is that the logic/setting to have it ranked has changed.</p> <p><strong>Todays logic – changed in October 2021</strong> <br /><a href="https://drive.google.com/uc?id=1IjFGmMdLJoVO_DQnjir95l7DfJPsy-KS"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://drive.google.com/uc?id=1Ba1GG60LxQLMJF8uGdEtFkxjnWH1miS-" width="644" height="198" /></a> </p> <p><strong>The old logic</strong></p> <a href="https://drive.google.com/uc?id=1dsben_clovv9vCNnzK6kltbIS7ynJoVr"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://drive.google.com/uc?id=1GjEa1INV8NvAtZzDhvO8oaLMNzVTEMwt" width="644" height="174" /></a> <p>The old logic introduced with SharePoint 2013 would start the block high up, and if results in the block was not clicked it would move down the page, and eventually off the page, which is what has happened for most customers over the years.</p> <p>The new logic now introduced will ALWAYS interleave the block on the page 1 results, never moving it off the page.</p> <h3>So how does this affect the API?</h3> <p>By default an API query will invoke query rules unless explicitly turned off, e.g. the above query <a title="https://techmikael.sharepoint.com/_api/search/query?querytext='mikael'&enablequeryrules=true&enableinterleaving=true&rowlimit=10&clienttype='ContentSearchHigh'&properties='EnableMultiGeoSearch2:true'" href="https://tenant.sharepoint.com/_api/search/query?querytext='mikael'&rowlimit=10">https://tenant.sharepoint.com/_api/search/query?querytext='mikael'&rowlimit=10</a></p> <p>As Modern Search was introduced quite some time back this has greatly reducing the use of the classic search center. This means that people haven’t clicked results in result blocks from quite some time, no clicks are recorded and the block moved off the page – never appearing in API queries.</p> <p>Now as the logic has changed, the blocks come back, which is not a bug, but maybe not expected.</p> <p>Together with query rules there is another API setting available, one I have never thought about, but it’s been there all along. “Enable Interleaving” which by default is set to true documented at <a title="https://learn.microsoft.com/en-us/previous-versions/office/sharepoint-csom/jj262234(v=office.15)" href="https://learn.microsoft.com/en-us/previous-versions/office/sharepoint-csom/jj262234(v=office.15">https://learn.microsoft.com/en-us/previous-versions/office/sharepoint-csom/jj262234(v=office.15)</a>.</p> <p>Of course, if you don’t need query rules for your scenario you should always disable them on the API call. Problem solved!</p> <p>Then again, using the PnP modern search web parts a common scenario is to use promoted results, and thus you need query rules enabled. Which leads to queries on people names triggering the original “People names rules” causing interleaving to happen and the results split into primary and secondary result tables in the response.</p> <p>The solution then is to set <strong>EnableInterleaving=false.</strong></p> <p>Changing the query to <a title="https://techmikael.sharepoint.com/_api/search/query?querytext='mikael'&enableinterleaving=false&rowlimit=10&clienttype='ContentSearchHigh'&properties='EnableMultiGeoSearch2:true'" href="https://contoso.sharepoint.com/_api/search/query?querytext='mikael'&enableinterleaving=false&rowlimit=10">https://contoso.sharepoint.com/_api/search/query?querytext='mikael'&enableinterleaving=false&rowlimit=10</a> ensure 10 results as expected in the primary result set.</p> <a href="https://drive.google.com/uc?id=1kQfZvsTVAU1tlMDTD0XR7Oa4lQCuT6ZU"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://drive.google.com/uc?id=1WMhh0-aXDt0ClbbuwIO_l19YHcTThduM" width="644" height="444" /></a> <p>I have released a fix to the Query Tool which by default will disable interleaving, or you can set it yourself.</p> <p><a title="https://github.com/pnp/PnP-Tools/releases" href="https://github.com/pnp/PnP-Tools/releases">https://github.com/pnp/PnP-Tools/releases</a> </p> <p>And I have made the same fix to the PnP Modern Search Web Parts v4.8, and any interleaving should be done manually at the template level if strictly needed.</p>Mikael Svensonhttp://www.blogger.com/profile/04135401463188945665noreply@blogger.comtag:blogger.com,1999:blog-5439950764176009449.post-35818665155252064662023-04-07T16:02:00.001+02:002023-04-07T16:02:26.133+02:00Query variable trick in Microsoft Search verticals (and classic)<p>Microsoft has been working on both classic and modern scenarios for Microsoft Search, and evaluating existing solutions to determine the best way to support query variables. This post is not exclusive to Microsoft Search, and the same technique can be used with any SharePoint classic search experience. The only difference is the type of query variables that are supported for each experience.</p> <p><em>For supported query variables in Microsoft Search modern experiences see </em><a title="https://learn.microsoft.com/en-us/microsoftsearch/manage-verticals#profile-query-variables" href="https://learn.microsoft.com/en-us/microsoftsearch/manage-verticals#profile-query-variables"><em>https://learn.microsoft.com/en-us/microsoftsearch/manage-verticals#profile-query-variables</em></a><em>.</em> </p> <p><em>For supported query variables in classic search see </em><a title="https://www.techmikael.com/2014/05/s15e03-query-variables-constant-trouble.html" href="https://www.techmikael.com/2014/05/s15e03-query-variables-constant-trouble.html"><em>https://www.techmikael.com/2014/05/s15e03-query-variables-constant-trouble.html</em></a>.</p> <h3>Solution</h3> <a href="https://drive.google.com/uc?id=1rpwPRCDWF6IexTm9iisRL2KXWwe96AHF"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://drive.google.com/uc?id=1MyWPXOrqBF_ewitJO78EPi0lhVeLrA-f" width="644" height="216" /></a> <p>The sample case solution provide an option to filter search results down a city. All items are tagged with a managed property <strong>City</strong> to allow for the filtering. On the SharePoint page of the solution the user can pick their own or a specific city. When picking their own, no query parameter is passed with the city. When picking a specific city the user is sent to a vertical in Microsoft Search passing the city value as a query string parameter:</p> <p><strong>_/layouts/15/search.aspx/<em>verticalname</em>?City=Helsinki</strong></p> <p><font face="Consolas"><font face="Arial">Which brings us to the query template to use, which will either</font></font></p> <p><font face="Consolas"><strong>{searchTerms} {?City:{Request.City} NOT UNIQUESTRING}{?City:{Profile.positions.detail.company.address.city}}</strong></font></p> <p><em>To see what properties you can use for a Profile query variable, view the output of </em><a title="https://graph.microsoft.com/beta/me/profile" href="https://graph.microsoft.com/beta/me/profile"><em>https://graph.microsoft.com/beta/me/profile</em></a><em> in e.g. Graph Explorer. For our test case the City location for a person is available via the query variable <strong>{Profile.positions.detail.company.address.city}</strong>. </em></p> <p>What the above query template achieve is: If a query string parameter <strong>City</strong> is present, this will be used as part of the query. If not present, the City value of the logged in users profile will be used instead. The <strong>{?}</strong> notation means that if a query variable is missing, the part enclosed within the braces will be removed all together from the template on evaluation.</p> <p>I’m using a trick with <strong>UNIQUESTRING</strong> (which could be any random unique string not present in the search index) to invalidate the last part of the query if we have a query string parameter in the URL. It adds invalid KQL sort of for a property which does not exist, and is thus ignored.</p> <p>Let’s add some examples to illustrate the evaluation where the ignored part of the query is highlighted in <font style="background-color: rgb(255, 255, 0);">yellow</font>, and the inclusion part in <font style="background-color: rgb(0, 255, 0);">green</font>. The user’s profile value for city is <strong>Oslo</strong>.</p> <h4>Scenario 1 – Click on Oslo</h4> <ul> <li>?City=Oslo</li> <li>Users City=Oslo</li> </ul> <p>Ending query: <font style="background-color: rgb(0, 255, 0);">City:Oslo</font> <font style="background-color: rgb(255, 255, 0);">NOT UNIQUESTRINGCity:Oslo</font>     <br /></p> <h4>Scenario 2 – Click on Helsinki</h4> <ul> <li>?City=Helsinki</li> <li>Users City=Oslo</li> </ul> <p>Ending query: <font style="background-color: rgb(0, 255, 0);">City:Helsinki</font> <font style="background-color: rgb(255, 255, 0);">NOT UNIQUESTRINGCity:Oslo</font></p> <h4>Scenario 3 – Click on My City</h4> <ul> <li>?City=<missing></li> <li>Users City=Oslo</li> </ul> <p>Ending query: <font style="background-color: rgb(0, 255, 0);">City:Oslo</font></p> <h4>Scenario 4 – Click on Helsinki (and missing a city in the profile)</h4> <ul> <li>?City=Helsinki</li> <li> Users City=<missing></li> </ul> <p>Ending query: <font style="background-color: rgb(0, 255, 0);">City:Helsinki</font> <font style="background-color: rgb(255, 255, 0);">NOT UNIQUESTRING</font></p> <h4>Scenario 5 – Click on My City and missing a city in the profile</h4> <ul> <li>?City=<missing></li> <li> Users City=<missing></li> </ul> <p>Ending query: <empty> </p> <p>And that’s all there is to it. By matching values on a users profile with values on other data you can create quick navigation and filtering scenarios. By adding SPFx into the mix even more control and logic can be built around the search results pages and passing in values. </p>Mikael Svensonhttp://www.blogger.com/profile/04135401463188945665noreply@blogger.comtag:blogger.com,1999:blog-5439950764176009449.post-42344793442875726302023-03-14T14:58:00.001+01:002023-03-14T15:00:26.744+01:00Retirement of custom default result sources in Microsoft Search for modern search experiences<p>In November 2021 I posted about bookmarks being the <a href="https://www.techmikael.com/2021/11/phase-1-of-bookmarks-to-take-over-for.html" target="_blank">successor feature of promoted results for organizational scoped searches in Microsoft Search</a>, which was the first step to modernize the Microsoft Search stack and remove dependencies on classic SharePoint search features and API’s.</p> <p>The next step is now under way, as announced by <a href="https://admin.microsoft.com/Adminportal/Home?ref=MessageCenter/:/messages/MC526131" target="_blank">MC526131 - Retirement of custom default result sources in Microsoft Search for modern search experiences</a>.</p> <a href="https://drive.google.com/uc?id=1Awi67om43Uv_S-IgqU3_W4mDw8hb05vc"><img title="00049" style="display: inline; background-image: none;" border="0" alt="00049" src="https://drive.google.com/uc?id=1elS88WEjZK8KvEzYR4HuUzPUoJOQCaRw" width="644" height="644" /></a> <p> </p> <p>For most customers the change, which will start April 10th 2023, should have no impact. The way KQL rewrite works for a default result source was never intended for modern search experiences as any change was applied to all verticals showing SharePoint and OneDrive content. The ability for an admin to edit and add KQL per vertical in the modern experience is a better and more accurate feature – succeeding the result source feature which doesn’t really work well in modern search experiences in SharePoint. See <a title="https://learn.microsoft.com/en-us/microsoftsearch/manage-verticals#keyword-query-language-kql" href="https://learn.microsoft.com/en-us/microsoftsearch/manage-verticals#keyword-query-language-kql">https://learn.microsoft.com/en-us/microsoftsearch/manage-verticals#keyword-query-language-kql</a> for more information on vertical management.</p> <p>I want to be crystal clear that nothing happens to classic search experiences nor to experiences which are powered by the SharePoint Search API. Everything keeps on working as before – it’s just Microsoft Search in out-of-the-box modern experiences which retires reading the setup.</p> <p>I also want to point out that this does not effect query rule triggered promoted results on SharePoint sites or SharePoint hub-sites, as the modern experience will show a promoted result for these scopes regardless of the result source they may have been targeted towards.</p> <p>And as a last note, this only applies to environment where search vertical administration is rolled out.</p> <p>That’s it and you can likely ignore this post as it should not affect you </p>Mikael Svensonhttp://www.blogger.com/profile/04135401463188945665noreply@blogger.comtag:blogger.com,1999:blog-5439950764176009449.post-34887241568416917842022-07-04T13:55:00.001+02:002022-07-04T13:55:06.649+02:00Surface Dynamics 365 Data in Microsoft Search<p><a href="https://drive.google.com/uc?id=1kPs1T-SucGx_uiDe2OOMivx3__RAAYL4"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://drive.google.com/uc?id=1J-K_BM1S8rJboApfzvD27Xd2GNZGjqHe" width="644" height="198" /></a></p> <p>If you’re a user of Dynamics 365 did you know that it’s now possible to surface search results from Dynamics 365 in Microsoft Search? </p> <p>Head over to <a title="https://docs.microsoft.com/en-us/microsoftsearch/manage-dynamics365" href="https://docs.microsoft.com/en-us/microsoftsearch/manage-dynamics365">https://docs.microsoft.com/en-us/microsoftsearch/manage-dynamics365</a>, or direct your admin to follow the directions on how to enable the experience.</p> <p><strong>Quick steps:</strong></p> <ul> <li>Navigate to <a title="https://admin.microsoft.com/Adminportal/Home?#/MicrosoftSearch/connectors" href="https://admin.microsoft.com/Adminportal/Home?#/MicrosoftSearch/connectors">https://admin.microsoft.com/Adminportal/Home?#/MicrosoftSearch/connectors</a></li> <li>Click “add a new app or service” <br /><a href="https://drive.google.com/uc?id=1YAH-3taGm6A6XByWCbNMDLo0J2kMeT10"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://drive.google.com/uc?id=1BEz7TwMThRfRDcgOHlWmGQnZTgyU8RrU" width="644" height="178" /></a></li> <li>Pick D365 and follow the setup wizard <br /><a href="https://drive.google.com/uc?id=1S5YQibXC3PE19BonftdXhftHjrPDdVZb"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://drive.google.com/uc?id=1I4cpHE37gqhrWRA45ApaPjODFsHvUUsW" width="236" height="159" /></a></li> </ul>Mikael Svensonhttp://www.blogger.com/profile/04135401463188945665noreply@blogger.comtag:blogger.com,1999:blog-5439950764176009449.post-40018644171994848682022-01-20T10:38:00.004+01:002022-01-20T10:38:32.953+01:00Sensible defaults – avoiding error on first navigation to the Files tab in a Teams channel<p><em>I won’t take credit for the solution myself, as this was shared to me by the awesome </em><a href="https://twitter.com/Remi749" target="_blank"><em>Remi Blom-Ohlsen</em></a><em>, who is too timid to share great tips with the world himself :)</em></p> <p>We’ve all been there, and if you create solutions for customers involving Teams you are bound to have encountered the issue. After the team is created and you immediately navigate to the Files tab in a channel, you get an error message.</p> <p><a href="https://drive.google.com/uc?id=1sfTaY5HFVYJNs2tY9nzNgH1wcrGrH44K"><img alt="image" border="0" height="484" src="https://drive.google.com/uc?id=1iBEywaf8iZLWUmp-zSPZabI6vZs0Kg_H" style="background-image: none; display: inline;" title="image" width="589" /></a></p> <p>Navigate to the Posts tab and back, and all is working.</p> <p><a href="https://drive.google.com/uc?id=18TY-cxD9UGwuRVXRvVMtlSwKBt3u8LuC"><img alt="image" border="0" height="484" src="https://drive.google.com/uc?id=17SaYxT4rJ3o6gXf296PnjIaZas_qpc48" style="background-image: none; display: inline;" title="image" width="573" /></a></p> <p>When creating Teams using out of the box user interfaces you still have to live with this. If you however use a custom ordering and provisioning solution you can via code fix this nuance for your users :)</p> <p><em>If you are patient and wait a tiny bit, the folder will be created for you. For those who are impatient and want to ensure everything is the best way possible for end user, they can continue to read.</em></p> <p>If your provisioning solution is using C# you can ensure the channel folder is creating using code like this. And the crux here is the <strong>FilesFolder</strong> property on the channel object.</p>
<pre class="brush: csharp;">public static async Task<DriveItem> InitTeamDrive(string GroupId, GraphServiceClient GraphClient = null)
{
var graphClient = <get your client here>;
var channels = await graphClient.Teams[GroupId].Channels.Request().GetAsync();
foreach (var channel in channels)
{
if (channel.DisplayName == "General")
{
var drive = await graphClient.Teams[GroupId].Channels[channel.Id].FilesFolder.Request().GetAsync();
return drive;
}
}
return null;
}</pre>
The similar direct graph call would be.
<pre class="brush: js;">
GET https://graph.microsoft.com/v1.0/teams/<group id>/channels/<channel id>/filesFolder
</pre>Mikael Svensonhttp://www.blogger.com/profile/04135401463188945665noreply@blogger.comtag:blogger.com,1999:blog-5439950764176009449.post-19849780381388059192021-11-18T15:50:00.003+01:002023-06-08T15:14:45.447+02:00Bookmarks to take over for promoted results in Microsoft Search<p>As announced in the M365 message center post <a href="https://admin.microsoft.com/?&source=applauncher&ref=MessageCenter/:/messages/MC293777" target="_blank">MC293777</a> Microsoft Search will over the course of November to December of this year execute phase one to deprecate the support of classic query rule based promoted results / best bets, and replace it fully with Bookmarks and Q&A answers.</p> <p><em><u>Message center announcement:</u> In order to improve the Microsoft Search experience, promoted results will no longer be supported in Microsoft Search for <strong>Organization level scoped</strong> searches and will be replaced by the Bookmarks and Q&A features.</em></p> <a href="https://drive.google.com/uc?id=1Ekh3sBRobuip21_vWZP31LIK8W9Dh-rJ"><img alt="image" border="0" height="358" src="https://drive.google.com/uc?id=1JcOBrBIRRHVEh9zL2_UI_x3FBBYUVrHP" style="background-image: none; display: inline;" title="image" width="644"></a> <a href="http://www.techmikael.com/2021/11/phase-1-of-bookmarks-to-take-over-for.html#more">Read more »</a>Mikael Svensonhttp://www.blogger.com/profile/04135401463188945665noreply@blogger.comtag:blogger.com,1999:blog-5439950764176009449.post-72178174459043781882021-06-10T17:17:00.001+02:002021-06-10T17:17:21.954+02:00Updated script to re-index user profiles for search<p><img alt="white printer paper on green typewriter" src="https://images.unsplash.com/photo-1585776245991-cf89dd7fc73a?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=80" width="640" height="427" /></p> <p>This has been on my mind for years and I finally got the time to create a new version of my PowerShell script to re-index user profiles for the scenario where you map a new UPA property to be used in search.</p> <p>You can pick up reindex-users-v2.ps1 from <a title="https://github.com/wobba/SPO-Trigger-Reindex" href="https://github.com/wobba/SPO-Trigger-Reindex">https://github.com/wobba/SPO-Trigger-Reindex</a>. The script allows for quicker updates especially for tenants with a lot of profiles as it uses the UPA bulk import API instead of iterating the UPA.</p> <p>See <a title="https://docs.microsoft.com/en-us/sharepoint/dev/solution-guidance/bulk-user-profile-update-api-for-sharepoint-online" href="https://docs.microsoft.com/en-us/sharepoint/dev/solution-guidance/bulk-user-profile-update-api-for-sharepoint-online">https://docs.microsoft.com/en-us/sharepoint/dev/solution-guidance/bulk-user-profile-update-api-for-sharepoint-online</a> and <a title="https://docs.microsoft.com/en-us/previous-versions/office/sharepoint-csom/mt642955(v=office.15)" href="https://docs.microsoft.com/en-us/previous-versions/office/sharepoint-csom/mt642955(v=office.15)">https://docs.microsoft.com/en-us/previous-versions/office/sharepoint-csom/mt642955(v=office.15)</a> for documentation.</p> <p><em><font size="2">Cover image by </font></em><a href="https://unsplash.com/@markuswinkler" target="_blank"><em><font size="2">Markus Winkler @ Unsplash</font></em></a></p>Mikael Svensonhttp://www.blogger.com/profile/04135401463188945665noreply@blogger.comtag:blogger.com,1999:blog-5439950764176009449.post-35027932584998040492021-05-05T14:14:00.001+02:002021-05-05T14:35:21.637+02:00Site descriptions are now searchable!! (and more)<a href="https://drive.google.com/uc?id=1XMdfJdBhHv1YkV3FQq9hqfN9WwMdVo5j"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://drive.google.com/uc?id=1Sc4LLAzJkDF-s3XQgbuJs9_Nc-DX1Z43" width="621" height="681" /></a> <p>“What????!” you might say, hasn’t it always been like that? And the answer is that ever since SharePoint 2013 it hasn’t. Because if it had, I would not be writing this – just saying.</p> <p>As a bonus if you create a column in a library named <strong>Description</strong>, the content of this property is now also searchable. See my old post <a title="https://www.techmikael.com/2014/12/solution-to-cannot-search-content-in.html" href="https://www.techmikael.com/2014/12/solution-to-cannot-search-content-in.html">https://www.techmikael.com/2014/12/solution-to-cannot-search-content-in.html</a> about this issue.</p> <p>That’s correct people, you get a 2 for 1 special as Microsoft Search has rectified a long time nuance. And I’ll take the credit for getting this fixed (with some awesome technical help from Himanshu on the Stream team) - I can be humble another time </p> <a href="https://drive.google.com/uc?id=1vIZ-6L4uTqYBkzTEeiI1MrjlWsfgoa8R"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://drive.google.com/uc?id=1RcvKZmj1xxiyVrQvH-jOQ2HagY9t9Q-i" width="644" height="219" /></a> <p><em>Note: The change applies to updated content, not content already in the index. For active sites it should fix itself, so no action needed on your part.</em></p> <h3>Technical explanation</h3> <p>For the site description (or the description of an Office 365 group or a Team) the crawled property storing the description value, <strong>ows_SiteDescription</strong>, was mapped to two managed properties:</p> <ul> <li>Description</li> <li>SiteDescription</li> </ul> <p>Neither which were marked as searchable, effectively removing the ability to get a match on normal user queries from a search box. We have now made a search schema change to map <strong>ows_SiteDescription</strong> to the managed property <strong>Contents</strong> in addition to the two existing ones, ensuring full-text search.</p> <p>Same goes for a SharePoint column/field named Description. Except this is a weird one as the crawled property for this column is <strong>Office:6</strong>, not <strong>ows_Description</strong>. To be on the safe side we have mapped both <strong>Office:6</strong> and <strong>ows_Description</strong> to <strong>Contents</strong> as well.</p> <p>Need a refresh on what makes content free-text searchable in SharePoint? Head over to <a title="https://www.techmikael.com/2014/07/what-makes-sharepoint-column-searchable.html" href="https://www.techmikael.com/2014/07/what-makes-sharepoint-column-searchable.html">https://www.techmikael.com/2014/07/what-makes-sharepoint-column-searchable.html</a>.</p> <p><em>Cover image by </em><a href="https://unsplash.com/@krivitskiy"><em>Alexander Krivitskiy@unsplash</em></a></p>Mikael Svensonhttp://www.blogger.com/profile/04135401463188945665noreply@blogger.comtag:blogger.com,1999:blog-5439950764176009449.post-26467995766747286902021-01-04T18:57:00.001+01:002021-01-04T18:57:27.680+01:00Microsoft Graph: Encoding and decoding the drive id<a href="https://drive.google.com/uc?id=1gkUzD9owIv6MKUf84nOglShLECJaawNG"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://drive.google.com/uc?id=1pC4K6MrwMcIyuglRHwWZxxhR0JEp5t9x" width="644" height="427" /></a> <p>If you have worked with the Microsoft Graph API and SharePoint items you might have encountered URL’s which include a drive id. Where you in SharePoint typically work with URL’s for a site and the document library, a drive id is an encoded representation of a document library location.</p> <p>The following Graph REST request will list all items in a specific document library:</p> <p>GET https://graph.microsoft.com/v1.0/drives/<strong>b!VvpCx03990mC5Lb5YxH0SUA9TgZHvEZImra6PMjrvbx85KUwT1BMTbhen6I6ffXL</strong>/root/children</p> <p>Fetching the item for a file you use this signature to retrieve the file itself where item id is part of the listing: <em>GET /drives/<strong>{drive-id}/</strong>items/<strong>{item-id}</strong></em></p> <p>With some reverse engineering you easily can figure out the drive-id is a prefixed base64 encoded string composed of the site id, web id and list id for a particular library.</p> <p>Using PowerShell here’s a few lines converting the drive id string to the correct guid’s and back:</p> <pre><font face="Courier New" size="2">$driveId = "b!VvpCx03990mC5Lb5YxH0SUA9TgZHvEZImra6PMjrvbx85KUwT1BMTbhen6I6ffXL" <br />$encodedDriveId = $driveId.Substring(2).Replace('_','/').Replace('-','+') <br />$bytes = [Convert]::FromBase64String($encodedDriveId)<br /><font face="Courier New" size="2"><font face="Courier New" size="2">$siteIdBytes = [byte[]]$bytes[0..15]<br />$siteIdGuid = New-Object Guid @(,$siteIdBytes) #site id<br /><br /><font face="Courier New" size="2"><font face="Courier New" size="2">$webIdBytes = [byte[]]$bytes[16..31]<br />$webIdGuid = New-Object Guid @(,$webIdBytes) #web id<br /><br />$listIdBytes = [byte[]]$bytes[32..47]<br />$listIdGuid = New-Object Guid @(,$listIdBytes) #list/library id<br /><br />$bytes = $siteIdGuid.ToByteArray() + $webIdGuid.ToByteArray() + $listIdGuid.ToByteArray()<br />$driveId = "b!" + [Convert]::ToBase64String($bytes)
</font></font></font></font></font></pre>
<p>The item-id part is a bit more tricky and looks to be some sort of base32 encoding of a SharePoint item’s unique id. As I haven’t figured out the mechanics you can still access the item by route of the list item unique id:</p>
<p><em>GET https://graph.microsoft.com/v1.0/drives/<strong>{drive-id}</strong>/list/items/<strong>{unique-id}</strong>/driveItem</em></p>
<p>Example: https://graph.microsoft.com/v1.0/drives/b!VvpCx03990mC5Lb5YxH0SUA9TgZHvEZImra6PMjrvbx85KUwT1BMTbhen6I6ffXL/list/items/7D0E814C-0798-4966-A20C-6DE4F27F2027/driveItem</p>
<p>Of course, if you already have the site id, web id, list id and unique item id, you can access a drive item using the following syntax as mentioned in my file preview post.</p>
<i>GET https://graph.microsoft.com/v1.0/sites/<b>{<a>site</a>-id},{web-id}</b>/lists/<b>{list-id}</b>/items/<b><a></a><a href="https://graph.microsoft.com/v1.0/sites/{site-id}/lists/{list-id}/items/">{</a>item- id}<i>/driveItem</i></b></i>
<p>Photo by <a title="https://unsplash.com/@maurosbicego" href="https://unsplash.com/@maurosbicego">https://unsplash.com/@maurosbicego</a></p>Mikael Svensonhttp://www.blogger.com/profile/04135401463188945665noreply@blogger.comtag:blogger.com,1999:blog-5439950764176009449.post-11239065842293155902020-11-13T17:57:00.001+01:002020-11-16T08:18:10.292+01:00Mapping or clearing crawled property to managed property mappings using PowerShell (or code)<a href="https://drive.google.com/uc?id=1wbelrxAltihbKmu4xjRw6IFqd58YEadU"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://drive.google.com/uc?id=1aqrni0PuWxqUe3LVnu6IkcCgKtmiZoMK" width="638" height="499" /></a> <p>Mapping a crawled property to a managed property in SharePoint Online is usually done via the user interface. A somewhat cumbersome task as you first have to create content with a value which will ensure the creation of a crawled property matching your SharePoint field (or column if you want). Once the crawled property is available you can map it to a managed property.</p> <p>Lately there has been issues where crawled properties are not listed in the admin UI due to a bug, and this blocks tenants from creating search solutions dependent on schema mappings. There are some workarounds available which you can check out at <a title="https://platinumdogs.me/2020/11/13/sharepoint-online-search-crawled-properties-not-created-not-showing-or-not-available/" href="https://platinumdogs.me/2020/11/13/sharepoint-online-search-crawled-properties-not-created-not-showing-or-not-available/">https://platinumdogs.me/2020/11/13/sharepoint-online-search-crawled-properties-not-created-not-showing-or-not-available/</a>.</p> <p>Instead of these workaround I figured I’d show how you can use search configuration XML files to accomplish the same task – a pattern I used many times back in the day when working on SharePoint 2013 on-premises and had to move search configurations between environments. These files together with the PnP cmdlet Set-PnPSearchConfiguration is a time saver. You can also use</p> <blockquote> <p><strong>Get-PnPSearchConfiguration -Scope Site -OutputFormat ManagedPropertyMappings</strong></p> </blockquote> <p>to see any mappings at a particular site.</p> <p><strong>The first bonus of my solution is that you can map a crawled property which don’t yet exists, as it will be created for you. No need to create content before you start mapping.</strong></p> <p><strong>The other bonus is that you can also clear out an existing mapping, reverting it to the default behavior. Particularly handy if you at a site scope override a global mapping, and later want to revert. Something you simply cannot do in the admin interface today.</strong> </p> <p><em>Note: The best way to create these files is to use a new site collection in either SharePoint Online or SharePoint 2013/2016/2019 where you are able to do the mappings. Manually create the needed mappings and export the search configuration file to be used in another environment (site, or tenant).</em></p> <p>The script currently works with <strong>ows_<fieldName></strong> crawled properties. Which means you need to figure out the name of the crawled property manually. (ows_ + internal name of the SharePoint Field). It will also only work with the reusable managed properties as we know the id’s of these beforehand. In order to make it work for other crawled properties the script must be expanded to support more property set id’s. Focusing on the set <em>00130329-0000-0130-c000-000000131346</em> should however cover most scenarios.</p> <a href="https://drive.google.com/uc?id=1h7MDmHSfGva7VFZduTaR8cWZCla8rQhP"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://drive.google.com/uc?id=1237TZj9sJqA6hm-FMsWmituLLUGfyiab" width="644" height="159" /></a> <p>Head over to <a title="https://github.com/wobba/SearchConfiguration" href="https://github.com/wobba/SearchConfiguration">https://github.com/wobba/SearchConfiguration</a> and fetch the files:</p> <ul> <li>MapCrawledPropertyToManagedProperty.ps1</li> <li>SearchMappingTemplate.xml</li> <li>SearchMappingReset.xml</li> </ul> <p>Check the top of the ps1 for usage. Happy property mapping!</p> <p><em>Cover photo by </em><a href="https://unsplash.com/@markuswinkler" target="_blank"><em>Markus Winkler @ Unsplash</em></a></p>Mikael Svensonhttp://www.blogger.com/profile/04135401463188945665noreply@blogger.comtag:blogger.com,1999:blog-5439950764176009449.post-78449084596356115482020-09-29T15:37:00.002+02:002022-02-09T17:13:16.048+01:00Search and modern multilingual pages in SharePoint Online<h3><a href="https://drive.google.com/uc?id=1QB-RdQ4EM_eeW3O_955r203FP9CoJVdA"><img alt="image" border="0" height="431" src="https://drive.google.com/uc?id=1TYrNs5NSEyOmirrNXHJeW2i1iUyrsIQ0" style="background-image: none; display: inline;" title="image" width="644" /></a></h3><p>The ability to create SharePoint pages in multiple languages was/is a popular feature for classic SharePoint publishing pages. If you work in an organization where your employees use multiple languages, for example English and Norwegian, creating side by side pages in native languages is beneficial both from a communication point of view and also helps to tailor the information related to countries/regions based on language.</p><p>Back in SharePoint 2013 the functionality was called <b>variations</b>. This time around it’s more aptly named the “multilingual feature”. You can read the feature announcement from June 2020 at the <a href="https://techcommunity.microsoft.com/t5/microsoft-sharepoint-blog/new-sharepoint-feature-multilingual-publishing-for-pages-and/ba-p/1432445">Microsoft Tech Community</a>.</p><p>While variations were an option for sites using the classic SharePoint publishing feature, the ability to create multilingual pages is currently enabled by default for Communication sites only.</p><blockquote><p><i>If you want to enable multilingual page support on a Team site you can do so by activating a hidden feature called <b>SitePagePublishing</b> using for example PnP PowerShell as a site owner.</i></p><p><i><font face="Consolas">Connect-PnPOnline </font></i><a href="https://contoso.sharepoint.com/sites/mysite"><i><font face="Consolas">https://contoso.sharepoint.com/sites/mysite</font></i></a><i><br /><font face="Consolas">Enable-PnPFeature -Identity f39dad74-ea79-46ef-9ef7-fe2370754f6f</font></i></p><p></p></blockquote><p>If you want to take advantage of the ability to author multilingual pages, head over to <a href="https://support.microsoft.com/en-us/office/create-multilingual-communication-sites-pages-and-news-2bb7d610-5453-41c6-a0e8-6f40b3ed750c#bkmk_enable">Create multilingual communication sites, pages, and news</a> which describes in detail how to turn on the capability as well as how to author the pages.</p><h3>Details needed for search</h3><p>What happens behind the scenes when you create multilingual pages? For one, each language copy is stored in its separate folder. In my case English is the primary site language, and I opted to have Norwegian as a secondary language.</p><p><a href="https://drive.google.com/uc?id=10NCFMabPOSI9J9aEm9Nb5MEkbekEj0j2"><img alt="image" border="0" height="213" src="https://drive.google.com/uc?id=12g3zymhgHIm6FrggAMaXFvUo9_d2iKL8" style="background-image: none; display: inline;" title="image" width="644" /></a></p><p>Two pages in the original language.</p><p><a href="https://drive.google.com/uc?id=1tsfH9X1HMKJIfP21hTCTr6NfklLGlOB7"><img alt="image" border="0" height="168" src="https://drive.google.com/uc?id=1AnjdIVtCbDVmRaD0ur1aaNFSZuvdcElF" style="background-image: none; display: inline;" title="image" width="644" /></a></p><p>One of the pages is translated.</p><p>Secondly, to connect and keep track of the original vs. the translated pages there are some internal properties in SharePoint per item keeping track of this.</p><table border="1" cellpadding="0" cellspacing="0"><tbody><tr><td valign="top" width="200"><p><b>SharePoint Column</b></p></td><td valign="top" width="200"><p><b>Search Managed Property</b></p></td><td valign="top" width="200"><p><b>Description</b></p></td></tr><tr><td valign="top" width="200"><p>_SPTranslatedLanguages</p></td><td valign="top" width="200"><p>SPTranslatedLanguages</p></td><td valign="top" width="200"><p>Source page stores a list of the language of all translated languages. <br />E.g. nb-no.</p></td></tr><tr><td valign="top" width="200"><p>_SPTranslationLanguage</p></td><td valign="top" width="200"><p>SPTranslationLanguage</p></td><td valign="top" width="200"><p>Translated page stores the language of the page.</p><p>E.g.: nb-no</p><p></p></td></tr><tr><td valign="top" width="200"><p>_SPTranslationSourceItemId</p></td><td valign="top" width="200"><p>SPTranslationSourceItemId</p></td><td valign="top" width="200"><p>Translates page stores a reference to the original page.</p><p>E.g: 1f50aa8b-d31e-415a-bc4a-4ced38f5cdc4</p><p></p></td></tr><tr><td valign="top" width="200"><p>_SPIsTranslation</p></td><td valign="top" width="200"><p>SPIsTranslation</p></td><td valign="top" width="200"><p>The translated page stores the boolean value <b>true</b> to indicate it’s a translation and not the original. The original article has no value.</p></td></tr></tbody></table><p>The desired behavior when searching is to return a page in the users’ display language if it exists. If a translation does not exist, fall back to the original language – which follows the default language of a site set at site creation.</p><p>The examples below explain the logic used by Microsoft Search, and you can replicate this yourself as well in custom solutions.</p><p>To return English pages returned the query would be:</p><p><font face="Consolas"><strong>(SPTranslationLanguage:en-us OR (NOT SPTranslatedLanguages:en-us AND NOT SPIsTranslation:true))</strong></font></p><p><a href="https://drive.google.com/uc?id=1ZYKyXQwUSDdPOiCjsYtJPWE0MJ0oh4-5"><img alt="image" border="0" height="245" src="https://drive.google.com/uc?id=1kn52UFVmOL86CNjjmhsj_edOmFDBMomz" style="background-image: none; border-color: currentcolor; border-image: none 100% / 1 / 0 stretch; border-style: initial; border-width: 0px; border: 0px currentcolor; display: inline;" title="image" width="644" /></a><br />Both pages returned in the original language - English.</p><p>To return Norwegian pages the query would be:</p><p><font face="Consolas"><strong>(SPTranslationLanguage:nb-no OR (NOT SPTranslatedLanguages:nb-no AND NOT SPIsTranslation:true))</strong></font></p><p><a href="https://drive.google.com/uc?id=1419DK0JpA5PfwFBTwGqty3yZ7rEw0lbL"><img alt="clip_image008" border="0" height="248" src="https://drive.google.com/uc?id=1f49slCYqDPP3C2DAGaEXoTjYXEnRvF0K" style="background-image: none; border-color: currentcolor; border-image: none 100% / 1 / 0 stretch; border-style: initial; border-width: 0px; border: 0px currentcolor; display: inline;" title="clip_image008" width="606" /></a><br />One translated page and one non-translated returned.</p><p>If you are using the PnP Modern Search web parts you can use the query variable <font face="Consolas">{PageContext.currentUICultureName}</font> to substitute the correct display language into the query.</p><p>Easy as pie :)</p><p><em>PS! For the KQL savvy, you can not replace the <strong>NOT</strong> operator with the <strong>–</strong> (minus) operator for boolean values – for some weird reason that fails.</em></p><p><em><font size="2">Cover photo by </font></em><a href="https://unsplash.com/@matreding" target="_blank"><em><font size="2">Mat Reding @ Unsplash</font></em></a></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p>Mikael Svensonhttp://www.blogger.com/profile/04135401463188945665noreply@blogger.comtag:blogger.com,1999:blog-5439950764176009449.post-42965819076134914542020-09-14T16:01:00.000+02:002020-09-14T16:02:20.451+02:00Microsoft Search vs. PnP Modern Search – a clash of titans!<p><img alt="man standing and walking going on boxing ring surrounded with people" src="https://images.unsplash.com/photo-1552072092-7f9b8d63efcb?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1000&q=80" width="640" height="427"></p> <p>Sorry for the clickbait title. I have been meaning to write about how I think about the out-of-the-box Microsoft Search vs. the PnP Modern Search web parts for a while, so here goes.</p> <p><b><i>Disclaimer:</i></b><i> I have been working with search for 20 years, enterprise search for 15 years and SharePoint and search for almost just as long. The opinions stated are my own and they are based on my experience with search in FAST ESP, SharePoint and Office 365 over the years and are not influenced by my role as a program manager on Microsoft Search. No money or breaking of fingers were involved in writing this post :)</i></p> <h3>A little history</h3> <p>With SharePoint 2013, Microsoft shipped many ways to customize how search worked. Both from a technical and user experience perspective. The more important one being the ability to use arbitrary HTML, CSS, and JavaScript in custom display templates with the Search Result web part and the Content by Search web part (CSWP).</p> <p>Fast forward to SharePoint Online and the release of modern SharePoint pages late 2016. Modern pages came with a new set of web parts and lacked the super-flexible CSWP. Modern pages did introduce the Highlighted Content web part (HCWP), positioned as <a href="https://support.microsoft.com/en-us/office/use-the-highlighted-content-web-part-e34199b0-ff1a-47fb-8f4d-dbcaed329efd">“...the newer, simplified version of the Content Search web part.”</a></p> <p>When customer transitioned from classic to modern a gap had been formed between the CSWP and the HCWP which needed filling. And this is where the awesome sharing in the SharePoint community comes in, put into a sharable system with <a href="https://pnp.github.io/">Microsoft 365 Patterns and Practices</a> (PnP).</p> <p>The first version of the <a href="https://microsoft-search.github.io/pnp-modern-search/">PnP Modern Search web parts</a> (MSWP) were added as a SharePoint Framework sample by <a href="https://twitter.com/FranckCornu">Franck Cornu</a> back in October of 2017. My first contribution to the sample was made in January of 2018 to include additions needed for a customer project I had at the time.</p> <p>Back then MSWP was one web part; the result web part which included an optional built-in refinement panel. The search box web part got introduced late February of 2018, with the vertical web part following later. My main reason for looking at the sample web part in the first place was the need of a roll-up web part for a project. The Highlighted Content web part (HCWP) lacked the needed templating required – and still does, and why bother develop something if it already exists? Much easier to add to a maintained code base compared to owning it completely on my own #lazyprogrammer.</p> <a href="https://drive.google.com/uc?id=1C1ME1sWt-XUIRiKge5HwgwgaxDq8K25g"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://drive.google.com/uc?id=1VBzH6BBSOeN8xfU_6PvdqThV6XrR_ybN" width="644" height="451"> <br></a><em><font size="2">Image by </font></em><a href="https://unsplash.com/@kennyzhang29" target="_blank"><em><font size="2">Zhang Kenny @ Unsplash</font></em></a><em><font size="2">. </font></em> <p>And this is where I believe the PnP Modern Search web parts has its sweet spot – bridge the gap between the classic Content by Search web part and the new Highlighted Content web part. This was my opinion back in 2018, and it still is in 2020. I actually formed the opinion back in 2016. That is 4 years and counting.</p> <a href="http://www.techmikael.com/2020/09/microsoft-search-vs-pnp-modern-search.html#more">Read more »</a>Mikael Svensonhttp://www.blogger.com/profile/04135401463188945665noreply@blogger.comtag:blogger.com,1999:blog-5439950764176009449.post-19590358245894066702020-06-02T17:22:00.001+02:002020-06-02T17:23:18.280+02:00One year anniversary as a blue badge at Microsoft<p><a href="https://drive.google.com/uc?id=1mV7-I24xcrLthsfKQbrCGYXa5WXf3S9A"><img width="400" height="300" title="cake" style="display: inline;" alt="cake" src="https://drive.google.com/uc?id=1RL47lihdJeGrBa2XpD2Eh-QgWPdr2WWP"></a></p><p>One year ago I joined the Microsoft Search Experiences team in Oslo as a program manager, and time has gone by really FAST (pun intended). Overall it has been an awesome experience - largely due to the great team I’m part of. It has been very different from my previous job as a consultant, thus hard to compare, but I’m not done yet and have things I want to accomplish while I’m still young.</p><p>Here’s a list of some of what I’ve been part of or accomplished over the past year – all non-NDA stuff :)</p><ul><li>I’ve written way fewer blog posts compared to the last years, which was expected, but I do hope to get the volume up a bit again.</li><li>Released my Troubleshooting Search in SharePoint Online self-help manual on Amazon</li><li>Two trips to India</li><li>Two trips to the US</li><li>Three trips to Tromsø (northern Norway)</li><li>Written about 4,000 e-mails – yeah, I know that’s not much at all, but it is for me</li><li>Presented at Ignite and SPSOslo (about what I usually do)</li><li>Made a lot of contacts across the v-team which Microsoft Search is across</li><li>Organized a hands & crafts x-mas social workshop for my team</li><li>Worked on multiple features underway – from small to large</li><li>Got the Microsoft Search code base up and running and did multiple pull requests as part of a hackathon week, fixing some real but minor issues </li><li>Won the business value award at an internal hackathon with my fellow hackers</li><li>Worked to align the out of the box Microsoft Search offering and messaging with the PnP Modern Search web parts</li><li>Talked to a good amount of high value customers on various search topics – which is not that different from talking to smaller customers as the search issues and needs are not that different except scale ;)</li><li>Still trying to see if we can expose the Live Persona Card in Office 365 as a re-usable control in SPFx (not given up yet)</li><li>…and more</li></ul><p>I’ve interacted and contributed on too many projects to count, and it has proved valuable to bring my SharePoint and Office 365 experience into the team. As Microsoft Search is expanding, SharePoint is still a large part of it content wise and knowing the inner workings when moving from classic to modern is never a bad idea.</p>Mikael Svensonhttp://www.blogger.com/profile/04135401463188945665noreply@blogger.comtag:blogger.com,1999:blog-5439950764176009449.post-76822246302652768802020-04-30T15:40:00.002+02:002020-06-03T10:46:17.534+02:00Governance tip on finding overshared content in O365/SharePoint<p><a href="https://drive.google.com/uc?id=1TgLN3gWcXr1tR_N5uDJW-7UxFd810Hcu"><img alt="image" border="0" height="610" src="https://drive.google.com/uc?id=1Yzygw9PRTebi6FpKY16BL_zzb_NKuoCY" style="background-image: none; display: inline;" title="image" width="644" /></a></p><p>Unless you have put in place the right governance measures you might at some point experience content showing up in search which shouldn't be there. A common problem are items overshared to the <strong>Everyone except external users</strong> group. Using search itself, you can easily find these items and put in place the right measures to remedy any oversharing.</p><p>When someone creates a sharing link on a document in SharePoint Online today, the sharing information is stored in a searchable managed property in the search index named <strong>SharedWithUsersOWSUSER</strong>. The same information is stored in the internal SharePoint item field named SharedWithUsers.</p><p>By issuing the query below as any user (as it’s explicitly shared with everyone and everyone has access) you can find all documents with an everyone sharing link attached to them. </p><p><strong>SharedWithUsersOWSUSER:spo-grid-all-users</strong></p><p>The same approach can be used with any claim/user/group as documented in the <a href="https://docs.microsoft.com/en-us/microsoft-365/compliance/keyword-queries-and-search-conditions?view=o365-worldwide#searchable-site-properties">official eDiscovery documentation</a>.</p><p>You can also try the below query to find items which are shared:</p><p><b>ViewableByExternalUsers:1 OR ViewableByAnonymousUsers:1</b></p><p>If you get the refiner values from SPSiteURL, you can aggregate all sites which have shared content.</p><p>If you want to remedy oversharing to everyone, you can turn off the showing the Everyone claim with SharePoint Online PowerShell:</p><p><strong>Set-SPOTenant -ShowEveryoneExceptExternalUsersClaim $false</strong></p><p>or with PnP PowerShell:</p><p><strong>Set-PnPTenant -ShowEveryoneExceptExternalUsersClaim $false</strong></p><p>This merely hides the claim from showing, so you might still want to run scheduled reports to find items which are shared with everyone in case you want to prevent this behavior.</p><p>Happy sharing!</p><p><em><font size="2">Image by </font></em><a href="https://unsplash.com/@markuswinkler"><em><font size="2">Markus Winkler @ Unsplash</font></em></a></p>Mikael Svensonhttp://www.blogger.com/profile/04135401463188945665noreply@blogger.comtag:blogger.com,1999:blog-5439950764176009449.post-47552856416654936582020-03-26T15:19:00.001+01:002020-03-26T15:23:16.034+01:00Searching within Office 365 Groups or Teams content<p><a href="https://drive.google.com/uc?id=1YivJ7beM0EEDAnTJhxqU_Sk6D9FdCgT3"><img width="644" height="412" title="image" style="display: inline; background-image: none;" alt="image" src="https://drive.google.com/uc?id=1X7HnZeanObaoyIYQ0k3ZgDFLHc65Rcz8" border="0"></a></p><p>There are at least three ways to limit the search results within a group or a team using the keyword query language (KQL). These are cases where the managed property used exists on all items for the site/group.</p><h3>Path</h3><p>If you know the URL of the groups site you can use a path filter, and remember the trailing slash (/) to avoid edge case inclusion of other data.</p><p><strong>path:https://contoso.sharepoint.com/teams/myteam/</strong></p><h3>Site Id</h3><p>If you know the underlying site id of the Groups site.</p><p><strong>SiteID:<guid></strong></p><h3>Group Id</h3><p>If you know the Group Id, meaning the AAD id of the group, you can use this as well.</p><p><strong>GroupId:<guid></strong></p><h3>Bonus: Search within all the groups a user is member of</h3><p>And here’s the kicker to effectively scope results to all the groups a user is member of. Say you have pulled out a list of all the groups a user is member of via the Microsoft Graph API: </p><pre><code>https://graph.microsoft.com/v1.0/me/memberOf/$/microsoft.graph.group<br>?$filter=groupTypes/any(a:a eq 'unified')</code></pre><p>Armed with all the group ids, you can issue a SharePoint Search REST query using a wildcard (*) as the query text and the following FQL in the <strong>refinementfilters</strong> property.</p><p><strong>GroupId:or(<guid1>,<guid2>,….)</strong></p><p><em>GroupId:or(81eb706e-2904-4ac6-89f4-a0cf9d59d1c4,79958190-024b-4c62-ab55-65dc9a066cac)</em></p><p>If you are a member of many groups, then I suggest using a POST payload instead of GET, and <em>refinementfilters</em> is not limited by 4k either (at the time of this writing) :) </p><p>See <a href="https://www.techmikael.com/2013/07/limiting-search-results-by-exact-time.html">https://www.techmikael.com/2013/07/limiting-search-results-by-exact-time.html</a> for an explanation of refinement filter usage.</p><p><em>Note: How the above syntax will work using the Microsoft Graph Search API which is in beta, is not known at this point.</em></p><p><em><font size="2">Photo by </font></em><a href="https://unsplash.com/@youngprodigy3"><em><font size="2">Mike Szczepanski @Unsplash</font></em></a></p>Mikael Svensonhttp://www.blogger.com/profile/04135401463188945665noreply@blogger.com