首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

ASP.NET 動態查詢條件建構器:參考 iTunes 智慧播放清單的巢狀邏輯實作

     編輯:ASP.NET 基礎

專案背景與挑戰

專案需求:MongoDB 存儲多種業務日誌,資料結構各異。需提供查詢介面供開發人員搜尋資料。初期嘗試讓使用者直接輸入 MongoDB JSON 查詢語法或 SQL,但學習成本過高,最終放棄。

靈感來源:iTunes 智慧播放清單

iTunes 智慧播放清單介面

iTunes 允許使用者動態新增「條件」與「條件群組」(相當於括號),支援無限層級巢狀邏輯(AND/OR)。這種直觀的視覺化交互完美解決了複雜查詢建構問題。

核心資料結構設計

抽象為兩類實體:

QueryGroup(查詢群組)

public class QueryGroup
{
    public GroupType GroupType { get; set; } // And / Or
    public List<QueryItem> Items { get; set; }
    public List<QueryGroup> Groups { get; set; }
}

QueryItem(查詢條目)

public class QueryItem
{
    public string Name { get; set; }        // 欄位名
    public QuerySymbol OperatorType { get; set; } // 運算子 (=, !=, >, <, LIKE...)
    public string Value { get; set; }       // 比對值
    public DataType ValueType { get; set; } // 資料型別 (String, Int, Double, DateTime)
}

GroupType 決定群組內邏輯為「全部符合」(AND) 或「任一符合」(OR),對應介面的「所有」/「任何」選項。

前端交互實作

動態查詢條件介面

採用 Bootstrap 建構,將 HTML 拆分為兩個隱藏模板:.query-group-template 與 .query-item-template。

關鍵 jQuery 事件綁定

// 初始化:載入一組預設群組,移除其刪除按鈕
$('#queryContainer').append($('.query-group-template>.query-group').clone());
$('#queryContainer>.query-group').first().find('.delete-query-group').remove();

// 新增單一條件
$('button.add-query-item').on('click', function () {
    $(this).closest('.query-group').append($('.query-item-template>.query-item').clone());
    return false;
});

// 新增子群組(巢狀)
$('button.add-query-group').on('click', function () {
    $(this).closest('.query-group').append($('.query-group-template>.query-group').clone());
    return false;
});

// 刪除群組(保護根群組不被刪除)
$('button.delete-query-group').on('click', function () {
    if (!$(this).closest('.query-group').parent().hasClass('query-group')) return false;
    $(this).closest('.query-group').remove();
    return false;
});

// 刪除單一條件
$('button.delete-query-item').on('click', function () {
    $(this).closest('.query-item').remove();
    return false;
});
註:原文使用 .live() 已棄用,現代專案請改用 .on() 委派事件。

前端資料序列化策略

避免傳遞散亂表單欄位,採用「表單 → JavaScript 物件 → JSON → Base64/URL 編碼」流程:

JavaScript 物件定義(欄位名與後端一致)

function QueryGroup() {
    this.GroupType = 0;
    this.Items = [];
    this.Groups = [];
}
function QueryItem() {
    this.Name = '';
    this.OperatorType = 0;
    this.Value = '';
    this.ValueType = 0;
}

遞歸構建物件樹

function GetQueryGroup(group) {
    group = $(group);
    var queryGroup = new QueryGroup();
    queryGroup.GroupType = parseInt(group.find('.group-type').val());

    // 處理 Items
    group.children('.query-item').each(function () {
        var item = new QueryItem();
        item.Name = $(this).find('.property-name').val();
        item.OperatorType = parseInt($(this).find('.operate-type').val());
        item.Value = $(this).find('.query-value').val();
        item.ValueType = parseInt($(this).find('.value-type').val());
        queryGroup.Items.push(item);
    });

    // 遞歸處理子 Groups
    group.children('.query-group').each(function () {
        queryGroup.Groups.push(GetQueryGroup(this));
    });

    return queryGroup;
}

提交前序列化

var rootGroup = GetQueryGroup($('#queryContainer>.query-group').first());
var json = encodeURIComponent(JSON.stringify(rootGroup));
// 送往後端...

後端反序列化與查詢轉換

ASP.NET MVC / Web API 反序列化

var json = Uri.UnescapeDataString(Request["query"]);
var rootGroup = JsonConvert.DeserializeObject<QueryGroup>(json);

遞歸轉換為查詢條件 (ICriteria / IMongoQuery)

public class QueryGroup
{
    public GroupType GroupType { get; set; }
    public List<QueryItem> Items { get; set; }
    public List<QueryGroup> Groups { get; set; }

    public ICriteria ToICriteria()
    {
        ICriteria result = null;
        foreach (var criteria in GetICriteriaList())
        {
            if (result == null) { result = criteria; continue; }
            if (GroupType == GroupType.AndAlso) result = result.Add(criteria);
            else if (GroupType == GroupType.OrElse) result = result.Or(criteria);
        }
        return result;
    }

    private List<ICriteria> GetICriteriaList()
    {
        var list = new List<ICriteria>();
        foreach (var item in Items)
        {
            list.Add(new Criteria(item.Name, item.OperatorType, 
                new QueryValue(item.ValueType, item.Value, FieldHierarchyLevel.Child)));
        }
        foreach (var group in Groups)
        {
            list.Add(group.ToICriteria()); // 遞歸
        }
        return list;
    }
}

取得 ICriteria 後即可直接傳給資料存取層執行查詢。

擴展性與應用場景

  • MongoDB:本專案直接轉為 IMongoQuery
  • SQL:同樣可轉換為 WHERE 子句與參數化查詢
  • Expression Tree:進階場景可轉為 Expression<Func<T, bool>> 供 LINQ 使用

Demo 動畫展示

動態查詢條件建構器操作示範

總結

透過「樹狀資料結構 + 模板化前端 + JSON 序列化 + 遞歸轉換」四步走策略,成功實作出支援無限巢狀 AND/OR 邏輯的動態查詢建構器。此架構解耦前後端,擴展性極佳,可快速適配不同資料源與查詢引擎。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved