This demo incorporates server-side semantic search into the DevExtreme DataGrid. Semantic search finds results based on meaning rather than exact wording, understanding the context and intent behind a question or phrase. This allows your DevExtreme-powered app to deliver more relevant answers by connecting related concepts, even if exact words differ.
To review benefits of this feature, search for dictionary entries and their descriptions and use synonyms or generic descriptions instead of exact search strings (such as "clothing" instead of a specific product name). You can fine-tune search results: use the Similarity Factor editor to change the search precision.
[note]
AI services used for this demo have been rate and data limited. As such, you may experience performance-related delays when exploring the capabilities of the DataGrid AI Assistant.
When connected to your own AI model/service without rate and data limits, semantic search will perform seamlessly, without artificial delays. Note that DevExtreme does not offer an AI REST API and does not ship any built-in LLMs/SLMs.
[/note]
This demo configures semantic filtering on the server (using AzureOpenAI embeddings). You can incorporate server-side semantic search using built-in DataGrid visual elements. In this demo, each request returns filtered data using two parameters:
After you enter a query in the search panel, the DevExtreme DataGrid passes the new search value to the backend and loads the filtered data set.
@using DevExtreme.MVC.Demos.Models.DataGrid
@(Html.DevExtreme().DataGrid<DictionaryItem>()
.ID("gridContainer")
.DataSource(d => d.WebApi()
.Controller("DataGridSemanticSearch")
.LoadAction("Get")
.Key("ID")
.LoadParams(new {
searchValue = new JS("getSearchValue"),
similarityFactor = new JS("getSimilarityFactor"),
})
)
.RemoteOperations(true)
.ShowBorders(true)
.Height(600)
.Scrolling(scrolling => scrolling.Mode(GridScrollingMode.Virtual))
.SearchPanel(searchPanel => searchPanel.Visible(true))
.OnEditorPreparing("onEditorPreparing")
.Columns(columns => {
columns.AddFor(m => m.ID).Width(50);
columns.AddFor(m => m.Name);
columns.AddFor(m => m.Description);
})
.Toolbar(toolbar => toolbar
.Items(items => {
items.Add()
.Location(ToolbarItemLocation.Before)
.Template(@<text>
<div style="display: flex; align-items: center;">
<span style="margin-right: 8px;">Similarity Factor:</span>
@(Html.DevExtreme().NumberBox()
.ID("similarityFactor")
.InputAttr("aria-label", "Similarity Factor")
.Value(0.31f)
.Min(0)
.Max(1)
.Format("0.00")
.Step(0.05f)
.ShowSpinButtons(true)
.OnValueChanged("onSimilarityFactorChanged")
)
</div>
</text>);
items.Add().Name("searchPanel");
})
)
)
<script>
let searchValue = "";
function onEditorPreparing(e) {
if (e.parentType === 'searchPanel') {
let searchTimeout;
e.editorOptions.onValueChanged = function (args) {
clearTimeout(searchTimeout);
searchTimeout = setTimeout(() => {
searchValue = args.value;
e.component.getDataSource().reload();
}, e.updateValueTimeout);
}
e.editorOptions.placeholder = 'Try: clothing';
}
}
function getSearchValue() {
return searchValue;
}
function getSimilarityFactor() {
const numberBox = $('#similarityFactor').dxNumberBox('instance');
return numberBox.option('value');
}
function onSimilarityFactorChanged(e) {
if (searchValue !== '') {
const grid = $('#gridContainer').dxDataGrid('instance');
grid.getDataSource().reload();
}
}
</script>
using DevExtreme.MVC.Demos.Models;
using DevExtreme.MVC.Demos.Models.DataGrid;
using DevExtreme.MVC.Demos.Models.SampleData;
using System;
using System.Linq;
using System.Web.Mvc;
namespace DevExtreme.MVC.Demos.Controllers {
public class DataGridController : Controller {
public ActionResult SemanticSearch() {
return View();
}
}
}
using DevExtreme.AspNet.Data;
using DevExtreme.AspNet.Mvc;
using DevExtreme.MVC.Demos.DataProviders;
using DevExtreme.MVC.Demos.Models.DataGrid;
using DevExtreme.MVC.Demos.Models.SampleData;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Http;
namespace DevExtreme.MVC.Demos.Controllers.ApiControllers {
public class DataGridSemanticSearchController : ApiController {
SmartFilterProvider smartFilter;
public DataGridSemanticSearchController(SmartFilterProvider smartFilterProvider) {
smartFilter = smartFilterProvider;
}
[HttpGet]
public async Task<object> Get(string searchValue, float similarityFactor, DataSourceLoadOptions loadOptions) {
if(string.IsNullOrEmpty(searchValue)) {
return DataSourceLoader.Load(SampleData.DictionaryItems, loadOptions);
}
await smartFilter.FillCacheAsync(new[] { searchValue });
var result = Search(searchValue, similarityFactor);
return DataSourceLoader.Load(result, loadOptions);
}
IEnumerable<DictionaryItem> Search(string searchValue, float similarityFactor = 0.31f) {
return SampleData.DictionaryItems
.Select(item => new {
Entry = item,
Similarity = smartFilter.GetSimilarity(DictionaryItem.GetItemDescription(item), searchValue)
})
.OrderByDescending(x => x.Similarity)
.Where(x => x.Similarity > similarityFactor)
.Select(x => x.Entry);
}
}
}
namespace DevExtreme.MVC.Demos.Models.DataGrid {
public class DictionaryItem {
public DictionaryItem(int id, string name, string description) {
ID = id;
Name = name;
Description = description;
}
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public static string GetItemDescription(DictionaryItem item) {
return $"{item.Name} - {item.Description}";
}
}
}
using DevExtreme.MVC.Demos.Models.DataGrid;
using System.Collections.Generic;
namespace DevExtreme.MVC.Demos.Models.SampleData {
public partial class SampleData {
public static readonly IEnumerable<DictionaryItem> DictionaryItems = new[] {
new DictionaryItem(1, "Car", "A vehicle with four wheels"),
new DictionaryItem(2, "Bus", "A large vehicle for transporting passengers"),
new DictionaryItem(3, "Tea", "A hot drink made from brewed leaves"),
new DictionaryItem(4, "Coffee", "A hot drink made from brewed beans"),
new DictionaryItem(5, "Computer", "An electronic device for processing data"),
new DictionaryItem(6, "Mouse", "An input device for controlling the cursor on the screen"),
new DictionaryItem(7, "Airplane", "An aircraft for transporting passengers and cargo"),
new DictionaryItem(8, "Table", "Furniture for working or dining"),
new DictionaryItem(9, "Chair", "A comfortable seat with armrests"),
new DictionaryItem(10, "Phone", "A device for voice and text communication"),
new DictionaryItem(11, "Book", "A printed publication with texts and illustrations"),
new DictionaryItem(12, "Pen", "A tool for writing with ink"),
new DictionaryItem(13, "Watch", "A device for measuring time"),
new DictionaryItem(14, "Television", "A device for watching videos and broadcasts"),
new DictionaryItem(15, "Camera", "A device for taking photographs"),
new DictionaryItem(16, "Bicycle", "A two-wheeled vehicle"),
new DictionaryItem(17, "Plate", "A dish for serving food"),
new DictionaryItem(18, "Cup", "A container for drinking hot beverages"),
new DictionaryItem(19, "Backpack", "A bag carried on the back"),
new DictionaryItem(20, "Calculator", "An electronic device for calculations"),
new DictionaryItem(21, "Tablet", "A mobile device with a touch screen"),
new DictionaryItem(22, "Keyboard", "An input device for typing text"),
new DictionaryItem(23, "Spoon", "A utensil for eating soups and cereals"),
new DictionaryItem(24, "Fork", "A utensil for picking up food"),
new DictionaryItem(25, "Knife", "A tool for cutting food"),
new DictionaryItem(26, "Lamp", "A lighting device"),
new DictionaryItem(27, "Wardrobe", "Furniture for storing clothes and things"),
new DictionaryItem(28, "Mirror", "An object for reflecting images"),
new DictionaryItem(29, "Microwave", "A device for quickly heating food"),
new DictionaryItem(30, "Refrigerator", "A device for keeping food at low temperatures"),
new DictionaryItem(31, "Vacuum Cleaner", "A device for cleaning dust and debris"),
new DictionaryItem(32, "Kettle", "A container for boiling water"),
new DictionaryItem(33, "Bottle", "A container for storing liquids"),
new DictionaryItem(34, "Glasses", "A device for correcting vision"),
new DictionaryItem(35, "Headphones", "A device for personal audio listening"),
new DictionaryItem(36, "Speaker", "A device for playing sound"),
new DictionaryItem(37, "Microphone", "A device for recording and transmitting sound"),
new DictionaryItem(38, "Mouse", "A small rodent"),
new DictionaryItem(39, "Power Bank", "A device for charging gadgets on the go"),
new DictionaryItem(40, "Monitor", "A screen for displaying information from a computer"),
new DictionaryItem(41, "Notebook", "A book of blank pages for writing notes"),
new DictionaryItem(42, "Pencil", "A tool for writing or drawing with graphite"),
new DictionaryItem(43, "Backpack", "A bag worn on the back for carrying items"),
new DictionaryItem(44, "Shoes", "Footwear for protection and comfort"),
new DictionaryItem(45, "Socks", "Garments worn on the feet"),
new DictionaryItem(46, "T-shirt", "A short-sleeved casual top"),
new DictionaryItem(47, "Jacket", "A garment for the upper body, typically having a front opening"),
new DictionaryItem(48, "Hat", "A head covering for warmth or fashion"),
new DictionaryItem(49, "Scarf", "A long piece of cloth worn around the neck"),
new DictionaryItem(50, "Gloves", "Hand coverings for warmth or protection"),
new DictionaryItem(51, "Umbrella", "A device for protection against rain or sun"),
new DictionaryItem(52, "Wallet", "A small case for holding money and personal items"),
new DictionaryItem(53, "Purse", "A handbag used by women to carry everyday items"),
new DictionaryItem(54, "Watch", "A timepiece worn on the wrist"),
new DictionaryItem(55, "Belt", "A strap worn around the waist"),
new DictionaryItem(56, "Ring", "A circular band worn on the finger"),
new DictionaryItem(57, "Necklace", "A piece of jewelry worn around the neck"),
new DictionaryItem(58, "Bracelet", "A piece of jewelry worn around the wrist"),
new DictionaryItem(59, "Earrings", "Jewelry worn on the earlobes"),
new DictionaryItem(60, "Sunglasses", "Eyewear for protection against sunlight"),
new DictionaryItem(61, "Notebook", "A portable computer"),
new DictionaryItem(62, "Printer", "A device that produces paper copies of documents"),
new DictionaryItem(63, "Router", "A device that forwards data packets between computer networks"),
new DictionaryItem(64, "Modem", "A device that modulates and demodulates signals for internet access"),
new DictionaryItem(65, "Smartphone", "A mobile phone with advanced features and computing capability"),
new DictionaryItem(66, "Blender", "An appliance for mixing or pureeing foods and liquids"),
new DictionaryItem(67, "Toaster", "A device for browning slices of bread"),
new DictionaryItem(68, "Oven", "An appliance for baking or roasting food"),
new DictionaryItem(69, "Stove", "An appliance for cooking food by direct heat"),
new DictionaryItem(70, "Dishwasher", "An appliance for cleaning dishes"),
new DictionaryItem(71, "Washing Machine", "An appliance for washing clothes"),
new DictionaryItem(72, "Dryer", "An appliance for drying clothes"),
new DictionaryItem(73, "Iron", "A device for smoothing wrinkles in fabric"),
new DictionaryItem(74, "Ironing Board", "A flat surface for ironing clothes"),
new DictionaryItem(75, "Broom", "A tool for sweeping floors"),
new DictionaryItem(76, "Dustpan", "A flat scoop for collecting dust and debris"),
new DictionaryItem(77, "Mop", "A tool for cleaning floors"),
new DictionaryItem(78, "Bucket", "A container for carrying liquids"),
new DictionaryItem(79, "Detergent", "A cleaning agent"),
new DictionaryItem(80, "Sponge", "A porous material for cleaning"),
new DictionaryItem(81, "Towel", "A piece of cloth for drying things"),
new DictionaryItem(82, "Toothbrush", "A brush for cleaning teeth"),
new DictionaryItem(83, "Toothpaste", "A paste for cleaning teeth"),
new DictionaryItem(84, "Shampoo", "A liquid for washing hair"),
new DictionaryItem(85, "Conditioner", "A product for making hair softer and more manageable"),
new DictionaryItem(86, "Soap", "A substance for washing and cleaning"),
new DictionaryItem(87, "Body Wash", "A liquid soap for cleaning the body"),
new DictionaryItem(88, "Lotion", "A cream for moisturizing skin"),
new DictionaryItem(89, "Deodorant", "A substance for preventing body odor"),
new DictionaryItem(90, "Perfume", "A fragrant liquid for applying to the body"),
new DictionaryItem(91, "Razor", "A tool for shaving hair"),
new DictionaryItem(92, "Shaving Cream", "A cream for softening hair before shaving"),
new DictionaryItem(93, "Hair Dryer", "A device for drying hair"),
new DictionaryItem(94, "Comb", "A tool for arranging hair"),
new DictionaryItem(95, "Hairbrush", "A brush for styling hair"),
new DictionaryItem(96, "Nail Clippers", "A tool for trimming nails"),
new DictionaryItem(97, "Nail File", "A tool for smoothing and shaping nails"),
new DictionaryItem(98, "Tweezers", "A tool for plucking hair or handling small objects"),
new DictionaryItem(99, "Scissors", "A tool for cutting"),
new DictionaryItem(100, "Band-Aid", "A small adhesive bandage for minor cuts and scrapes")
};
}
}
File not found
File not found