Back to "المعلومات الاستخبارات - الجزء 2: الموجزات والإشارات والأجزاء"

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

C# Privacy Product Segmentation

المعلومات الاستخبارات - الجزء 2: الموجزات والإشارات والأجزاء

Friday, 26 December 2025

داخل الجزء الأول لقد غطينا فلسفة و سلسلة اللمحة العامة. الجزء الأول لقد بنينا مولد بيانات العينة

الآن دعونا نبني النظام الأساسي. هذا الجزء يركز على:

  1. هيكل التعريف لـ صفر-PII - الجلسات الإكهامية مقابل النبذات الثابتة
  2. الملحقات والأوزان - ما الذي نتعقبه وكيف يتراكم
  3. التعاريف - العضوية الغزّية مع قواعد مرجحة (الحدث الرئيسي)
  4. نمط - نشر بيانات موثوقة (مفصلة في الجزء 3)

هذا هو عينة من المشروع (Mostlylucid.SegmentCommerce- نموذج تجاري إلكتروني صغير يبين الأنماط الأساسية - إنه مبسط عمداً لإظهار المفاهيم بوضوح، ولكنه يشمل أيضاً أنماط بنية تحتية حقيقية (مناولة الرسائل التي تعتمد على الخارج، معالجة خلفية الوظائف، فهرسة JOSONB) التي يمكن أن تقوم بتكبيرها أفقياً في الإنتاج.

فكروا في هذا على أنه "أنماط إنتاج في عامل واحد-اصف." نفس هيكل الرموز يعمل سواء كنت تدير عملية واحدة أو توزع الخدمات.

خيارات التكنولوجيا

لقد اخترنا مبسطة ومتماسكة إبقاء العينة واضحة مع بيان أنماط الإنتاج.

الفرضSSSSQL + الـججفف: 1 قاعدة بيانات

بدلاً من قواعد بيانات المتجه المنفصلة، واصفات الرسالة، وطبقات كشط، نستخدم المرشّسSQL:

flowchart LR
    App[ASP.NET Core] --> PG[(PostgreSQL)]
    
    PG --> JSONB[JSONB<br/>interests]
    PG --> Vector[pgvector<br/>embeddings]
    PG --> Queue[Queue tables<br/>jobs, outbox]
    PG --> FTS[Full-text<br/>tsvector]
    
    style PG stroke:#2f9e44,stroke-width:3px
    style JSONB stroke:#1971c2,stroke-width:2px
    style Vector stroke:#1971c2,stroke-width:2px
    style Queue stroke:#1971c2,stroke-width:2px
    style FTS stroke:#1971c2,stroke-width:2px
  • (مُنْسِس) لـ مرن chemas (لا منفصل NoSSQL)
  • (ج) مُنْفِجِكَر للترميزات (لا يوجد Qdrt/Pinecone)
  • المحتويات/الملاحظ الوظائف (لا Resedis/RabbitMQ)
  • (أ) مقدم مقدم النص الكامل (لا تُبحَث)

واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد، واحد.

HTMX + Alpin.js: Server-Driven UI

<!-- Instant search (no page reload) -->
<input 
    hx-get="/api/search" 
    hx-trigger="keyup changed delay:300ms" 
    hx-target="#results" />
  • XXXX: الخادم يقدم جزئيات (لا JJUNSON / morelating)
  • الألابين: لا يجوز القيام بغير خطوة بناءة
  • التعزيز التدريجي: يعمل بدون JS، أفضل مع ذلك

SPA مثل UX مع خادم reendering البساطة.

الموارد الأساسية: الأنماط القابلة للتوزيع

تطبيق واحد، لكن مقياس الأنماط:

  • صندوق خارجي (فعاليات DB) JIU مبادلة لحافلة رسائل
  • **** )ليسن/نوتيفي( ● مبادلة مجمع العمال
  • مُح الجلسة □ مقايضة الرقم القياسي لأسعار الاستهلاك المنفصل

بداية بسيطة، توزيع عند الحاجة.

ماذا تَجَنَّينا

  • لا توجد قاعدة بيانات ناقلات منفصلة (pgved هو مُسند)
  • لا يوجد إطار عمل للورقة المشتركة (HTMX + الألب أبسط)
  • لا توجد خدمات صغرى حتى الآن (تعمل بطاريات بالوحدنة أو التوزيع)
  • لا يوجد Dokker compus Sprawl (واحد DB, واحد تطبيق)

التحدي الصفري

يقوم المستخدمون التقليديون بتتبع تخزين المعلومات التي يمكن التعرف عليها: الأسماء، البريد الإلكتروني، هويات المستخدم المرتبطة بالسلوك.

نحن نخزن الأنماط السلوكية، وليس الهويات.

flowchart LR
    subgraph "Traditional Approach"
        User1[User: [email protected]] --> Behavior1[Bought headphones]
        Behavior1 --> PII1[(PII Database)]
    end
    
    subgraph "Zero-PII Approach"
        User2[Anonymous Session] --> Behavior2[Bought headphones]
        Behavior2 --> Pattern[(Category: tech<br/>Signal weight: 1.0)]
    end
    
    style PII1 stroke:#c92a2a,stroke-width:3px
    style Pattern stroke:#2f9e44,stroke-width:3px

البصيرة الرئيسية: أنت لست بحاجة إلى معرفة منظمة الصحة العالمية شخص ما هو لمعرفة ما هم مهتمون به.

أولاً - لمحة عامة

ويتألف النظام من ثلاث طبقات أساسية:

flowchart TB
    Browser[Browser] --> Session[Session Collector]
    Session --> Profile[Persistent Profile]
    Profile --> Segments[Segment Service]
    
    Session -->|in-memory only| Cache[(IMemoryCache)]
    Profile -->|elevated signals| DB[(PostgreSQL + JSONB)]
    Segments -->|memberships| UI[Segment Explorer UI]
    
    style Session stroke:#1971c2,stroke-width:3px
    style Profile stroke:#2f9e44,stroke-width:3px
    style Segments stroke:#fab005,stroke-width:3px
    style Cache stroke:#e64980,stroke-width:2px
  1. مُج إجتماع الجلسة - الإشارات السلوكية (العروض، النقرات، العربات) (التاريخ فقط)
  2. الجدول المُجَرَّد -المرتفعات عالية القيمة الإشارات، مصالح الحساب قاعدة بيانات
  3. **** - تقييم الملامح مقارنة بالقواعد، وإسناد العضوية

التفريق المؤجك َّرهذه ليست تفاصيل التنفيذ - إنه قرار خاص ببنيان الخصوصية.

موجزات وقائع الجلسات: التشدد داخل الذاكرة (مخبأة لـ FLU)

(أ) ما يلي: (الذاتيعيشون في IMemoryCache مع انتقــال لا تلمس قاعدة البيانات أبداً.

وهذا قيد معماري معماري صعب: بيانات الدورة لا يمكن أن تستمر. فهي تجمع الإشارات أثناء الزيارة وتطرد بعد 30 دقيقة من عدم النشاط عن طريق سياسة مخابئ LFU (أقل البلدان استخداماً في وقت لاحق) تحت ضغط الذاكرة.

المُوسَجِل: النموذج الداخلي في المُذكِر

// Mostlylucid.SegmentCommerce/Models/SessionProfile.cs
public class SessionProfile
{
    public string SessionKey { get; set; } = string.Empty;

    // Category interest scores: { "tech": 0.75, "fashion": 0.25 }
    public Dictionary<string, double> Interests { get; set; } = new();

    // Detailed signal counts: { "tech": { "product_view": 5, "add_to_cart": 1 } }
    public Dictionary<string, Dictionary<string, int>> Signals { get; set; } = new();

    // Products viewed this session
    public List<int> ViewedProducts { get; set; } = new();

    // Session context (device, referrer domain, time-of-day)
    public SessionContext? Context { get; set; }

    // Aggregates
    public double TotalWeight { get; set; }
    public int SignalCount { get; set; }
    public int PageViews { get; set; }
    public int ProductViews { get; set; }
    public int CartAdds { get; set; }

    // Timestamps
    public DateTime StartedAt { get; set; } = DateTime.UtcNow;
    public DateTime LastActivityAt { get; set; } = DateTime.UtcNow;

    // Link to persistent profile (if fingerprint resolved)
    public Guid? PersistentProfileId { get; set; }
}

مخزنة في IMMMorChech (أو مع انتهاء الإنزلاق

// Mostlylucid.SegmentCommerce/Services/Profiles/SessionCollector.cs
_cache.Set(sessionKey, sessionProfile, new MemoryCacheEntryOptions
{
    SlidingExpiration = TimeSpan.FromMinutes(30),
    Priority = CacheItemPriority.Normal, // LFU eviction under memory pressure
    
    // CRITICAL: Eviction callback decides whether to elevate to persistent profile
    PostEvictionCallbacks =
    {
        new PostEvictionCallbackRegistration
        {
            EvictionCallback = async (key, value, reason, state) =>
            {
                if (value is SessionProfile session && ShouldElevate(session))
                {
                    // Only NOW do we write to database (persistent profile)
                    await ElevateToProfileAsync(session);
                }
                // Otherwise: session is gone forever
            }
        }
    }
});

القيود:

  • أولاً - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -:: تُحيى الدورات فقط فقط في المخبأ (مجلّات أو هويّات الخزنة مثل Redis)
  • LF & LF: جلسات الاستخدام المنخفض: تُطرد أولاً تحت ضغط الذاكرة
  • التأجيلبعد 30 دقيقة من آخر نشاط:
  • إفكآخر فرصة لرفع إشارات عالية القيمة قبل فقدانها
  • لا يوجد أي انتعاش: App rether = جميع الجلسات المفقودة (ما لم تستخدم بطاقة الهوية المُعَدَّة، لكنها لا تزال مُعَدَّة)

قرار (بشأن الارتفاع)

private bool ShouldElevate(SessionProfile session)
{
    // Elevate if:
    // - User added to cart (high intent)
    // - User completed purchase (conversion)
    // - Fingerprint was resolved (identity established)
    // - Session weight exceeds threshold (engaged visitor)
    
    return session.CartAdds > 0 
        || session.TotalWeight > 5.0 
        || session.PersistentProfileId.HasValue;
}

لماذا يُؤَجِّل إعادة العودة؟

هذا هو فقط فقط في الوقت الذي يقوم فيه المخبأ بإخلاء الجلسة:

  1. نحن نعرف تاريخ الدورة الكامل
  2. يمكننا تقييم المشاركة الكاملة
  3. نتجنب تخزين جلسات منخفضة القيمة (عرض الصفحة الواحدة، ارتداد)
  4. نحن نضمن أن الدورات لا تستمر بالخطأ

إذا لم نرقي أثناء الإخلاء، الجلسة ستكون إلى الأبد إلى الأبدهذا هو التصميم

الموضوع: ما نتتبعه (السلامة)

public class SessionContext
{
    public string? DeviceType { get; set; }        // "mobile", "desktop"
    public string? EntryPath { get; set; }         // "/products/tech" (no query params)
    public string? ReferrerDomain { get; set; }    // "google.com" (domain only, not full URL)
    public string? TimeOfDay { get; set; }         // "morning", "afternoon"
    public string? DayType { get; set; }           // "weekday", "weekend"
}

إشعار ما هو غير هنا: عناوين IP، عوامل المستخدم، كامل الأحرف، تتبع بكسلز. نحن نلتقط )الأنماطلا معلومات قابلة للتحديد.

ما هي الاشارات ؟

A A 1 ف-4، 1 ف-3، 1 خ م، 1 خ ع (رأ)، 1 خ ع (ر أ)، 1 خ ع (رأ) هو حقيقة سلوكية يتم التقاطها أثناء عمل المستخدم. بدلاً من تتبع "من"، نتتبع "ما حدث".

هذا المفهوم يأتي من )أ(- حقائق قصيرة الأجل توجد في نافذة مربوطة وعصر خارج بشكل طبيعي. "api.rate_limited" أو "gateway.slow" لتنسيق السلوك بدون ربط ضيق.

هنا نطبق نفس النمط على سلوك المستخدم:

  • العرضproduct_view (الوزن: 0.10)
  • **** → add_to_cart (الوزن: 0.35)
  • **** → purchase (الوزن: 1.00)

الإشارات هي: عن السنة عن السنة (الانتهاء من الدورة)، صفر-PII )لا هوية( **** (الضـوء - الوعـي).

بصمات الأصابع (بطاقة هوية الزيرو- المكيَّز)

إلى ربط الجلسات بدون تتبع الكعك، نستخدم وضع علامة٩- ويحسب المتصفح مفرشاً من الإشارات )المنطقة الزمنية، دقة الشاشة، مُصَرِّر WebGL، بصمة القماش( ويرسل الرسائل. « إلا الها » أي : : كل ما قبلها وما قبلها وما قبلها وما قبلها إلا كل كل ما قبل هذا إلا كل إما إما إما إما إما إما : كل إما إما إما إما : كل إما إما إما : كل كل كل إما إما إما إما إما : كل كل إما إما إما إما : : كل كل إما إما : كل كل كل لا لا لا إما : : كل كل كل كل لا لا لا لا لا إلا كل هذه إلا كل كل كل شيء قبل هذا : كل كل كل كل كل لا لا لا لا لا لا إلا كل هذه إلا كل كل كل هذه إلا كل كل كل كل لا لا لا لا لا لا إلا كل كل كل إلا كل كل كل هذه إلا كل كل كل لا لا لا لا لا لا لا لا إلا إلا إلا إلا كل إلا كل إلا كل إلا كل إلا كل كل كل كل لا لا لا لا لا لا لا إلا إلا إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل كل كل كل كل لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا إلا إلا إلا إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل كل كل إلا كل إلا كل كل كل كل كل كل كل لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا لا إلا إلا إلا إلا إلا إلا إلا إلا إلا إلا إلا إلا إلا إلا إلا إلا إلا إلا إلا إلا إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل إلا كل كل إلا كل كل كل كل كل كل إلا كل إلا كل كل إلا كل إلا كل إلا كل كل كل إلا كل كل كل كل كل كل كل كل إلا كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل كل ثالثاً - /api/fingerprint.

الـ خادم HMACs التي تهش مع مفتاح سرّي، يجعله مقرّب موقع وغير قابل للإستعمال في مكان آخر.

هذا الشفرة مكيفة من مشروع الكشف عن المشروع، حيث تستخدم لتحديد الخردة نفس التقنية، غرض مختلف

// Mostlylucid.SegmentCommerce/ClientFingerprint/fingerprint.js
// Collect signals (browser capabilities, not PII)
var signals = [
    Intl.DateTimeFormat().resolvedOptions().timeZone,
    navigator.language,
    screen.width + 'x' + screen.height,
    // ... (see full code)
];

// Hash locally
var hash = hash(signals.join('|'));

// Send only the hash via sendBeacon
navigator.sendBeacon('/api/fingerprint', JSON.stringify({ h: hash }));

الخادم:

// Server HMACs the client hash with a secret key
var profileKey = HMACSHA256(clientHash + secretKey);

الآن لدينا معرف مستقر، مقرب للموقع بدون بسكويت أو سطر محلي. (بآلاف الجيب) (مأخوذة في معظم الأحيان من الكشف عن الخلايا القاعية).

أنواع الإشارة والدرجات

الإجراءات المختلفة لها مستويات نوايا مختلفة. نحن نموذج هذا مع ****.

(أ) التسلسل الهرمي للواثق

// Mostlylucid.SegmentCommerce/Data/Entities/Profiles/SignalEntity.cs
public static class SignalTypes
{
    // Passive signals (low intent)
    public const string PageView = "page_view";              // 0.01
    public const string CategoryBrowse = "category_browse";  // 0.03
    public const string ProductImpression = "product_impression"; // 0.02

    // Active signals (medium intent)
    public const string ProductView = "product_view";        // 0.10
    public const string ProductClick = "product_click";      // 0.08
    public const string Search = "search";                   // 0.05

    // High-intent signals
    public const string AddToCart = "add_to_cart";           // 0.35
    public const string AddToWishlist = "add_to_wishlist";   // 0.25
    public const string ViewCart = "view_cart";              // 0.15
    public const string BeginCheckout = "begin_checkout";    // 0.40

    // Conversion signals (highest intent)
    public const string Purchase = "purchase";               // 1.00
    public const string Review = "review";                   // 0.60
    public const string Share = "share";                     // 0.50

    public static readonly Dictionary<string, double> BaseWeights = new()
    {
        { PageView, 0.01 },
        { ProductView, 0.10 },
        { AddToCart, 0.35 },
        { Purchase, 1.00 },
        // ... (see full code for complete list)
    };

    public static double GetBaseWeight(string signalType)
    {
        return BaseWeights.GetValueOrDefault(signalType, 0.05);
    }
}

ولهذا السبب فإن هذا يهم:

  • (بآلاف دولارات الولايات المتحدة)0.01لن يهيمن على الإشارة
  • يضاف إلى النقل (يضاف إلى النقل)0.35() هو إشارة قوية نواة
  • 1.00هو أقوى إشارة

وهذا التسلسل الهرمي يمنع "التصفح عن طريق الدفع" من تلويث التوصيف.

مُنتَزَع الجلسة: تسجيل الإشارات (المراسَل فقط)

// Mostlylucid.SegmentCommerce/Services/Profiles/SessionCollector.cs
public async Task<SessionProfile> RecordSignalAsync(
    SessionSignalInput input, CancellationToken ct = default)
{
    var sessionKey = input.SessionKey;
    
    // Get or create session FROM CACHE (never DB)
    var session = _cache.Get<SessionProfile>(sessionKey);
    
    if (session == null)
    {
        session = new SessionProfile
        {
            SessionKey = sessionKey,
            StartedAt = DateTime.UtcNow
        };
    }

    session.LastActivityAt = DateTime.UtcNow;

    var weight = input.Weight ?? SignalTypes.GetBaseWeight(input.SignalType);

    // Update in-memory aggregates
    session.TotalWeight += weight;
    session.SignalCount++;

    if (!string.IsNullOrEmpty(input.Category))
    {
        session.Interests.TryGetValue(input.Category, out var currentScore);
        session.Interests[input.Category] = currentScore + weight;
    }

    if (input.SignalType == SignalTypes.AddToCart)
    {
        session.CartAdds++;
    }

    // Put back in cache with sliding expiration
    _cache.Set(sessionKey, session, new MemoryCacheEntryOptions
    {
        SlidingExpiration = TimeSpan.FromMinutes(30),
        Priority = CacheItemPriority.Normal,
        PostEvictionCallbacks = { /* elevation callback */ }
    });

    return session;
}

بسبب:

  • انت في - مِمَجوري (لا تكتب كتابة DB)
  • (النفقات العامة للمعاملات المتسلسلـة)
  • لا اتصالات شبكية (مخبأ محلي)

الملامح الثابتة: إشارات مسموعة

عندما تظهر دورة من الجلسات نية عالية (الخيارات المضافة، المشتريات)، نرفع الإشارات إلى المرفق.

العنصر الثابت: الملامح الطويلة الأجل

// Mostlylucid.SegmentCommerce/Data/Entities/Profiles/PersistentProfileEntity.cs
[Table("persistent_profiles")]
public class PersistentProfileEntity
{
    [Key]
    public Guid Id { get; set; } = Guid.NewGuid();

    [Required]
    [MaxLength(256)]
    public string ProfileKey { get; set; } = string.Empty;

    // How this profile is identified (Fingerprint, Cookie, Identity)
    public ProfileIdentificationMode IdentificationMode { get; set; }

    // Behavioral data (all JSONB)
    [Column("interests", TypeName = "jsonb")]
    public Dictionary<string, double> Interests { get; set; } = new();

    [Column("affinities", TypeName = "jsonb")]
    public Dictionary<string, double> Affinities { get; set; } = new();

    [Column("brand_affinities", TypeName = "jsonb")]
    public Dictionary<string, double> BrandAffinities { get; set; } = new();

    [Column("price_preferences", TypeName = "jsonb")]
    public PricePreferences? PricePreferences { get; set; }

    [Column("traits", TypeName = "jsonb")]
    public Dictionary<string, bool> Traits { get; set; } = new();

    // Computed segments
    public ProfileSegments Segments { get; set; } = ProfileSegments.None;

    [Column("llm_segments", TypeName = "jsonb")]
    public Dictionary<string, double>? LlmSegments { get; set; }

    // Vector embedding for similarity matching
    [Column("embedding", TypeName = "vector(384)")]
    public Vector? Embedding { get; set; }

    // Statistics
    public int TotalSessions { get; set; }
    public int TotalSignals { get; set; }
    public int TotalPurchases { get; set; }
    public int TotalCartAdds { get; set; }

    public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
    public DateTime LastSeenAt { get; set; } = DateTime.UtcNow;
    public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
}

لم يُقِر صفر:

  • ProfileKey هو a HMAC asish (لا يمكن عكسه)
  • IdentificationMode يُخبرنا كيف تم تحديده (النثرب/البكر/الكوكي/اللوجين)
  • كل البيانات هي الاشارات السلوكيةلا معلومات شخصية

باء - الرفع: الدورة

public async Task ElevateToProfileAsync(
    SessionProfileEntity session, 
    PersistentProfileEntity profile, 
    CancellationToken ct = default)
{
    if (session.IsElevated)
        return;

    // Merge interests (use higher value)
    foreach (var (category, score) in session.Interests)
    {
        if (!profile.Interests.ContainsKey(category) || 
            profile.Interests[category] < score)
        {
            profile.Interests[category] = score;
        }
    }

    // Update stats
    profile.TotalSessions++;
    profile.TotalSignals += session.SignalCount;
    profile.TotalCartAdds += session.CartAdds;
    profile.LastSeenAt = DateTime.UtcNow;
    profile.UpdatedAt = DateTime.UtcNow;

    // Mark session as elevated
    session.IsElevated = true;
    session.PersistentProfileId = profile.Id;

    // Clear segment cache (will be recomputed)
    profile.SegmentsComputedAt = null;
    profile.EmbeddingComputedAt = null;

    await _db.SaveChangesAsync(ct);
}

عندما يحدث الارتفاع:

  • بعد النقلة تضاف عبارة (عالي النية)
  • بعد الشراء (التحويل)
  • عندما يختار المستعملون الثبات (الآداب/البكر/البكر/الكوكي/اللوتين)

التعاريف:

لقد قمنا بطرح أجزاء لجزئين. الآن دعونا نقوم بالتوصيل. الأجزاء هي الأنشطة من كل تلك الاشارة المجموعة - يجيبون "أي نوع من المتسوقين هو هذا؟"

لماذا العضوية الجازية؟

التجزئ التقليدي ثنائي: إما أن تكون في الجزء أو لا. هذا يخلق مشاكل:

flowchart LR
    subgraph "Binary Segmentation"
        Profile1[3 purchases] -->|"Threshold: 5"| Out[NOT High-Value]
        Profile2[5 purchases] -->|"Threshold: 5"| In[High-Value]
    end

عميل لديه 4 مشتريات يعامل بنفس الطريقة مع واحد مع صفر. هذا خطأ.

مززِزِف كلّ ملفّف ملفّف a رقم (صفر-1):

(بآلاف دولارات الولايات المتحدة) |-----------|--------|-------------| □ لا □ لا □ لا □ □ □ □ □ □ □ □ □ □ 2 □ لا □ لا □ ▪ ٤ □ لا □ لا □ □ □ ٥ + + □ نعم □ □ 5 + □ □ نعم □

الآن يمكنك أن تضفي طابعاً خاصاً تناسبياً: "تقريباً من العملاء ذوي القيمة العالية" يحصلون على معاملة مختلفة قليلاً عن "لا مكان قريب".

هيكل الجزء معرف

// Mostlylucid.SegmentCommerce/Services/Segments/SegmentDefinition.cs
public class SegmentDefinition
{
    public string Id { get; set; }           // "tech-enthusiast"
    public string Name { get; set; }          // "Tech Enthusiasts"
    public string Description { get; set; }   // "Users with strong interest in technology"
    public string Icon { get; set; }          // "🔧"
    public string Color { get; set; }         // "#3b82f6"

    public List<SegmentRule> Rules { get; set; } = [];

    // How rules combine: All (AND), Any (OR), Weighted (sum)
    public RuleCombination Combination { get; set; } = RuleCombination.Weighted;

    // Minimum score to be "a member" (0-1)
    public double MembershipThreshold { get; set; } = 0.3;

    public List<string> Tags { get; set; } = [];  // For filtering/grouping
}

حفظ:: ما الذي يمكنك التحقق منه

كل قاعدة تقيّم بُعداً واحداً من الملامح:

public enum RuleType
{
    CategoryInterest,  // Check interests.tech, interests.fashion, etc.
    BrandAffinity,     // Check brandAffinities.Sony, brandAffinities.Nike, etc.
    PriceRange,        // Check price preferences (budget vs luxury)
    Trait,             // Check boolean traits (prefersDeals, browsesExtensively)
    Statistic,         // Check totalPurchases, totalSessions, totalCartAdds
    TagAffinity,       // Check affinities.gadgets, affinities.organic, etc.
    Recency,           // Check days since last activity
    Expression         // Custom expressions (advanced)
}

المشغلون

public enum RuleOperator
{
    GreaterThan,       // value > threshold
    GreaterOrEqual,    // value >= threshold
    LessThan,          // value < threshold
    LessOrEqual,       // value <= threshold
    Equal,             // value == threshold
    NotEqual,          // value != threshold
    Contains,          // for array/string checks
    Between,           // for ranges
    In, NotIn          // for set membership
}

طريقة الجمع

كيفية الجمع بين قواعد متعددة في نتيجة نهائية:

public enum RuleCombination
{
    All,      // AND logic: Score = min(all rule scores). All rules must pass.
    Any,      // OR logic: Score = max(all rule scores). Any rule can pass.
    Weighted  // Weighted sum: Score = Σ(rule.weight × rule.score) / Σ(rule.weight)
}

عدد مرات هو الأكثر شيوعاً هذا يسمح لك أن تقول "المصلحة الشاملة تهم 60%، مسائل الاستقامة 30%، علاقة العلامة التجارية تهم 10%."

أمثلة

هذه هي الأجزاء الافتراضية في مشروع العينة:

1 - المهن الفنية

new SegmentDefinition
{
    Id = "tech-enthusiast",
    Name = "Tech Enthusiasts",
    Description = "Users with strong interest in technology products",
    Icon = "🔧",
    Color = "#3b82f6",
    MembershipThreshold = 0.35,
    Rules =
    [
        new() { 
            Type = RuleType.CategoryInterest, 
            Field = "interests.tech", 
            Operator = RuleOperator.GreaterOrEqual, 
            Value = 0.4, 
            Weight = 0.6,  // 60% of score
            Description = "Tech interest > 40%" 
        },
        new() { 
            Type = RuleType.TagAffinity, 
            Field = "affinities.gadgets", 
            Operator = RuleOperator.GreaterOrEqual, 
            Value = 0.2, 
            Weight = 0.2,  // 20% of score
            Description = "Likes gadgets" 
        },
        new() { 
            Type = RuleType.TagAffinity, 
            Field = "affinities.electronics", 
            Operator = RuleOperator.GreaterOrEqual, 
            Value = 0.2, 
            Weight = 0.2,  // 20% of score
            Description = "Likes electronics" 
        }
    ]
}

مثال التقييم:

  • لديه ملف interests.tech = 0.72, affinities.gadgets = 0.31, affinities.electronics = 0.15
  • القاعدة 1: 0.72 >= 0.4 ° 0. 1 (عتبة التجاوز)
  • القاعدة 2: 0.31 > = 0.2
  • القاعدة 3: القاعدة 3: 015 < 0.15 > 0, 0, 0, 0, 0, 0, 0,75 (الجزء: 0.15/0.2)
  • النتيجة النهائية: (1.0××0.6 + 1.0×0.2 + 0.75×0.2) / 1. 0.95
  • 0.95 > = عتبة 0.35 عضو لديه ثقة بنسبة 95 في المائة

2 - المنكوبون في السيارات

new SegmentDefinition
{
    Id = "cart-abandoner",
    Name = "Cart Abandoners",
    Description = "Users who add items to cart but don't complete purchase",
    Icon = "🛒",
    Color = "#ef4444",
    MembershipThreshold = 0.4,
    Rules =
    [
        new() { 
            Type = RuleType.Statistic, 
            Field = "totalCartAdds", 
            Operator = RuleOperator.GreaterOrEqual, 
            Value = 3, 
            Weight = 0.5, 
            Description = "3+ cart adds" 
        },
        new() { 
            Type = RuleType.Statistic, 
            Field = "totalPurchases", 
            Operator = RuleOperator.LessThan, 
            Value = 2, 
            Weight = 0.5, 
            Description = "Few purchases" 
        }
    ]
}

هذا يلتقط "الأضافات للعربة ولكن لا يشتري" نمط - التماثل لحملات الإنعاش.

3 - كبار العملاء

new SegmentDefinition
{
    Id = "high-value",
    Name = "High-Value Customers",
    Description = "Customers who make frequent purchases and spend above average",
    Icon = "💎",
    Color = "#8b5cf6",
    MembershipThreshold = 0.4,
    Rules =
    [
        new() { 
            Type = RuleType.Statistic, 
            Field = "totalPurchases", 
            Operator = RuleOperator.GreaterOrEqual, 
            Value = 3, 
            Weight = 0.4, 
            Description = "3+ purchases" 
        },
        new() { 
            Type = RuleType.PriceRange, 
            Field = "priceRange", 
            Value = "100-10000",  // High-end shoppers
            Weight = 0.3, 
            Description = "High price range" 
        },
        new() { 
            Type = RuleType.Recency, 
            Field = "lastSeen", 
            Operator = RuleOperator.LessThan, 
            Value = 30, 
            Weight = 0.3, 
            Description = "Active in last 30 days" 
        }
    ]
}

4 - الصياصون

new SegmentDefinition
{
    Id = "bargain-hunter",
    Name = "Bargain Hunters",
    Description = "Price-sensitive shoppers who love deals and discounts",
    Icon = "🏷️",
    Color = "#22c55e",
    MembershipThreshold = 0.3,
    Rules =
    [
        new() { 
            Type = RuleType.PriceRange, 
            Field = "priceRange", 
            Value = "0-75",  // Budget shoppers
            Weight = 0.5, 
            Description = "Low price preference" 
        },
        new() { 
            Type = RuleType.Trait, 
            Field = "traits.prefersDeals", 
            Value = true, 
            Weight = 0.3, 
            Description = "Prefers deals" 
        },
        new() { 
            Type = RuleType.Statistic, 
            Field = "totalCartAdds", 
            Operator = RuleOperator.GreaterThan, 
            Value = 5, 
            Weight = 0.2, 
            Description = "Shops around" 
        }
    ]
}

وتشمل العينة 10 أجزاء تغطي أنماط التجارة الإلكترونية الشائعة:

● القطاع / / / / / / / / o / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / - القواعد الرئيسية |---------|------|-----------|----------| □ الزبائن ذوي الجدارة العالية □ 3 + 3 + المشتريات، إنفاق مرتفع، معاملة حديثة لكبار الشخصيات، برامج الولاء □ □ التوصيات المتعلقة بمنتجات التكنولوجيا □ الموضة إلى الأمام □ □ الاهتمام بالموضة ، الزيارات المتعددة □ توصيات نمطية □ □ • يفضّل صيّادون المقايضة على نطاق سعري منخفض، ويفضّل الصفقات، ويفضّل أن يقدّم إخطارات بشأن البيع. • دورات لزائرين جدد، لا توجد مشتريات في الخدمة، عروض للشراء الأول عدد قليل من المشتريات □ بريداً الكترونياً للانتعاش □ • الرعاية المنزلية، النشاط الأخير • الاهتمام بالرياضة، الصفات الصحية، التركيز على منتجات الملاءمة 5+ المشتريات، 10++ دورات - الاحتفاظ، مكافآت □ باحثون في ارشادات عالية ، احذية على نطاق واسع ، ارشادات مسهبة ، ادوات مقارنة ، معلومات مفصّلة □

الخدمات القطاعيـة: عضويـات الحوسبة

الـ SegmentService يُقيّم الملامح مقارنة بجميع قواعد القطاع:

// Mostlylucid.SegmentCommerce/Services/Segments/SegmentService.cs
public SegmentMembership EvaluateSegment(ProfileData profile, SegmentDefinition segment)
{
    var ruleScores = new List<RuleScore>();
    
    foreach (var rule in segment.Rules)
    {
        var (score, actualValue) = EvaluateRule(profile, rule);
        ruleScores.Add(new RuleScore
        {
            RuleDescription = rule.Description,
            Score = score,
            Weight = rule.Weight,
            ActualValue = actualValue  // For transparency
        });
    }

    // Combine based on segment's combination method
    double finalScore = segment.Combination switch
    {
        RuleCombination.All => ruleScores.Min(r => r.Score),
        RuleCombination.Any => ruleScores.Max(r => r.Score),
        RuleCombination.Weighted => ComputeWeightedScore(ruleScores),
        _ => 0
    };

    return new SegmentMembership
    {
        SegmentId = segment.Id,
        SegmentName = segment.Name,
        Score = Math.Round(finalScore, 3),
        IsMember = finalScore >= segment.MembershipThreshold,
        RuleScores = ruleScores,
        Confidence = score switch  // Human-readable
        {
            >= 0.8 => "Very High",
            >= 0.6 => "High",
            >= 0.4 => "Medium",
            >= 0.2 => "Low",
            _ => "Very Low"
        }
    };
}

ا_ أدخل

وتشمل كل عضوة من الدول الأعضاء ما يلي: القيمة الفعلية الذي قاد إلى النتيجة:

// What the UI receives:
{
    "segmentId": "tech-enthusiast",
    "segmentName": "Tech Enthusiasts",
    "score": 0.95,
    "isMember": true,
    "confidence": "Very High",
    "ruleScores": [
        { "description": "Tech interest > 40%", "score": 1.0, "actualValue": "0.72" },
        { "description": "Likes gadgets", "score": 1.0, "actualValue": "0.31" },
        { "description": "Likes electronics", "score": 0.75, "actualValue": "0.15" }
    ]
}

لا يمكن (ب) أن يُرى ما يلي: هذا أمر حاسم بالنسبة للشفافية والامتثال للناتج المحلي الإجمالي.

تدفق الإشارة: من جهة إلى أخرى

هذه هي الطريقة التي تصبح بها وجهة نظر المنتج جزء من العضوية:

sequenceDiagram
    participant Browser
    participant Cache as SessionCache
    participant Outbox as Outbox
    participant Segment as SegmentService

    Browser->>Cache: Product view (category: "tech")
    Cache->>Cache: Update in-memory session
    Note over Cache: interests.tech += 0.10
    
    Browser->>Cache: Add to cart (high intent)
    Cache->>Outbox: Publish elevation event
    Outbox->>Outbox: Write to outbox table
    
    Note over Outbox: Background worker processes
    Outbox->>Segment: Elevate to PersistentProfile
    
    Segment->>Segment: Evaluate segment rules
    Note over Segment: interests.tech: 0.72 >= 0.40 ✓<br/>Score: 0.95, IsMember: true
    Segment-->>Browser: Segment memberships + explanations

الـ مخرج الإطار نمط

تدفق جميع الإجراءات الهامة من خلال (بدولارات الولايات المتحدة(أ)- آلية التوجيه الأولي:

flowchart LR
    Action[Cart Add] --> TX[Single Transaction]
    TX --> DB[(Save + Outbox)]
    DB --> Worker[Background Worker]
    Worker --> Route[Route to Handlers]
    
    style TX stroke:#2f9e44,stroke-width:3px

لماذا؟ لماذا؟ البيانات والوقائع التجارية مكتوبة في صفقة واحدة. الأحداث لا يمكن أن تضيع. الفشلات تعود تلقائياً بالعكس المتسارع.

// Every action publishes to outbox in the same transaction
await using var transaction = await _db.Database.BeginTransactionAsync(ct);

cart.Items.Add(new CartItem { ProductId = productId });
await _db.SaveChangesAsync(ct);

_outbox.Publish(OutboxEventTypes.ProductAddedToCart, new { ProductId = productId });
await _db.SaveChangesAsync(ct);

await transaction.CommitAsync(ct);
// Event is now guaranteed to be processed

الجزء الثالث ويغطي تنفيذ الإطار الكامل: قائمة الوظائف، والاستماع/الانصات/NOTIFY للشحن الفوري، ومنطق إعادة المحاولة، وأنماط التوسيع.

ما هو التالي

وقد شمل هذا الجزء ما يلي:

  • هيكل التعريف لـ صفر-PII (الجلسات التي تُعقد في البحار الافتراضية مقابل النبذات الثابتة)
  • التعاريف مع العضوية الغامضة والقواعد المرجحة
  • الـ جزء منSServ مع معمّد مع مع

الجزء الثالث تتعمق في:

  • المجموعة التنفيذية من النموذج - النشر الموثوق به للحدث وجهاز التوجيه الوحيد
  • **** مع التمهيدSSQL SKIP LOCKED لجامم مـن
  • المحتويات/الملاحظ (لا يوجد اقتراع)
  • أولاً أولاً أولاً وشفّاة - لوحة "مصالحك" ومستكشف القطاع

الاجزاء هي الناتج العملي لهذا النظام. انهم يجيبون "أي نوع من التوابل هو هذا؟" مع درجات ضبابية، وليس دلاءات ثنائية. وكل مستخدم يستطيع ان يرى بالضبط لماذا هم في جزء.

logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.