शून्य PIIC ग्राहक - पार्ट 2: प्रोफ़ाइल, सिग्नल व खण्ड (हिन्दी (Hindi))

शून्य PIIC ग्राहक - पार्ट 2: प्रोफ़ाइल, सिग्नल व खण्ड

Friday, 26 December 2025

//

26 minute read

में पार्ट 1 इस बारे में हमने तत्त्वज्ञान और श्रृंखला - क्रम पर चर्चा की । पार्ट 1. 1 हम नमूना डाटा जेनरेटर बनाया.

अब हम कोर तंत्र का निर्माण करते हैं. इस भाग पर ध्यान केंद्रित करता है:

  1. शून्य- आरआई प्रोफ़ाइल बिल्डर - एपीगर्मल सत्रों को scting प्रोफ़ाइल
  2. सिग्नल तथा भार - हम क्या ट्रैक और कैसे यह इकट्ठा होता है
  3. आंकड़ा इनकोड में त्रुटि - वज़न के नियमों के साथ सदस्यता (सबसे मुख्य घटना)
  4. आउटबॉक्स पैटर्न पूर्वावलोकन - विश्वस्त घटना प्रकाशन ( पार्ट 3)

यह है नमूना परियोजना (Mostlylucid.SegmentCommerce(C) - एक छोटा सा इम्पमाइट डेमो जो मुख्य पैटर्न दिखाता है. यह स्पष्ट रूप से प्रदर्शित करने के लिए स्पष्ट रूप से सरल है, लेकिन यह भी स्पष्ट रूप से स्पष्ट रूप से सरल है, लेकिन इसमें वास्तविक 'बाहर आधारित संदेश नियंत्रण, पृष्ठभूमि कार्य प्रक्रिया, JSONBobing) है कि आप उत्पादन में क्षैतिज रूप से स्केल करना चाहते हैं.

इसके बारे में सोचो "एक एकल-apps फार्म कारक में". वही कोड संरचना काम करती है कि आप एक प्रक्रिया चल रहे हैं या पूरे सेवाओं के पार वितरित कर रहे हैं.

तकनीक के चुनाव

और हमने (उनकी स्थिति को) जानते हुए उन्हें सारे संसारवालों के मुक़ाबले मं चुन लिया सरल, कोस्टेचर स्टैक उत्पादन पैटर्न प्रदर्शित करते समय नमूना स्पष्ट रखने के लिए.

एसक्यूएल + pgvor्टर: एक डाटाबेस

अलग सदिश डाटाबेस, संदेश क़तार, तथा क क्षमािंग परतों, के बजाए, हम उपयोग करते हैं एसक्यूएल:

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
  • JSONबी अंतर्निर्मित प्रसंग (कोई अलग नहीं) के लिए
  • पीगवर्टर एम्बेडिंग के लिए (कोई क्यूकेट/ मिटाया नहीं)
  • गीत/ अनिल कार्य के लिए (कोई रेड/कुटएमक्यू नहीं)
  • टीवरक्टर संपूर्ण पाठ के लिए (कोई एल- सर्च नहीं)

एक कनेक्शन पूल. एक बैकअप.

HMAX + अ6.js: सर्वर Rann यूआई

<!-- Instant search (no page reload) -->
<input 
    hx-get="/api/search" 
    hx-trigger="keyup changed delay:300ms" 
    hx-target="#results" />
  • एचएमएमएक्स: सर्वर अनुवाद आंशिकता का अनुवाद करता है (कोई JSON पूर्वप्रयोग नहीं)
  • **यू. एस.**एक निर्माण चरण के बिना रीस्थन:
  • प्रगतिशील सुधार: इनकार करनेवालों के बिना काम करता है, इसके साथ बेहतर

एसएपी जैसा यूएक्स सर्वर- नाप के साथ.

एनईएस. कोर: अप्रयोगीय पैटर्न

एकल app, परंतु पैटर्न स्केल:

  • जाती डाक फ्लश करें (_u) (DB कार्यक्रम) बस के लिए खोजें
  • कार्य कतार ( गीत/दोनों_ नहीं) कामकाजी पूल के लिए स्वेप
  • सत्र संस्करण अलग API के लिए मिसालें

जब आवश्यक हो तो सरल प्रारंभ करें.

हम किन बातों से दूर रह गए

  • कोई अलग वेक्टर डाटाबेस नहीं (pwrented)
  • कोई जेएस फ्रेमवर्क नहीं (HMX + अप्रयोग्य सरल है)
  • कोई माइक्रोस्कोप अब तक नहीं होता (प्रयोगात्मक काम करता है या वितरित किया जाता है)
  • कोई डॉकर बनाएंर नहीं (एक डीबी, एक app)

शून्य- जीआईपीआई चुनौती

पारंपरिक उपयोक्ता ट्रैकिंग जानकारी: नाम, ई- मेल, उपयोक्ता आईडी बर्ताव से जुड़ा हुआ है. GDPP और गोपनीयता नियमों से यह बढ़ती समस्या पैदा होती है. हमारा तरीका अलग है:

हम व्यवहारिक पैटर्न, पहचान नहीं.

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. खण्ड सेवा - नियमों के विरुद्ध प्रोफ़ाइलों का मूल्यांकन करें, सदस्यता दें

गंभीर भेद: सत्र एप्टल हैं. प्रोफ़ाइल जारी हैं. यह एक कार्यान्वयन विवरण नहीं है - यह एक गोपनीयता सामग्री निर्णय है.

सत्र प्रोफ़ाइल: सख्त

सत्र हैं अच्छी तरह सेवे अंदर रहते हैं IMemoryCache एक्सपोजर तथा एक्सपोजर सहित डाटाबेस को कभी नहीं छूता.

यह एक हार्ड कवरिंग अवरोध है: सत्र डाटा बना नहीं सकता. यह 30 मिनट के दौरान संकेत इकट्ठा करता है और 30 मिनट की निष्क्रियता के दौरान (L) स्मृति दबाव के तहत कैश नीति इस्तेमाल की जाती है.

सत्र

// 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; }
}

मैं रिपरीश में जमा (या आईडीडीडीक) समय - समय - समय पर जमा हुआ

// 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
            }
        }
    }
});

हार्ड सीमाएँ:

  • शून्य दुर्घटनात्मक लगन: सत्र जीते हैं सिर्फ कैश में (मैंगासीक या आईडीसीश लाल की तरह)
  • देश - भक्‍ति: स्मृति दबाव के नीचे पहले कम से कम सत्र निकाल दें
  • स्लाइडिंग एक्सपायरेशनपिछले उपक्रम से 30 मिनट
  • एडक्शन कॉलबैक: अंतिम मौका उच्च मूल्य संकेतों को बढ़ाने का इससे पहले कि वे खो गये हैं
  • कोई सुधार नहीं: फिर आरंभ करें = सभी सत्र गुम हो गए (कोई वर्णन नहीं दिया गया है), लेकिन अभी भी एडिप्रिकल)

एलीवेशन निर्णय (प्रयोग पर)

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"
}

ध्यान दें क्या है नहीं यहाँ: आईपी पता, उपयोक्ता एजेंट, पूर्ण यूआरएल, ट्रैकिंग पिक्सेल. हम कैप्चर करते हैं. संदर्भ पैटर्न, जानकारी पहचान नहीं है.

सिग्नल क्या है?

ए सिग्नल एक उपयोक्ता कार्रवाई के दौरान व्यवहारत्मक तथ्य लिया गया है. "कौन" पर ट्रैक करने के बजाय, हम ट्रैक "क्या हुआ" पर ट्रैक करें.

इस धारणा की वजह से एपेर्निक संकेतस्वाभाविक रूप से इस प्रणाली में, संचालन संकेतों की तरह इंगित करता है "api.rate_limited" या "gateway.slow" बिना तंग जोड़ों के बर्ताव को निर्देशांक करने के लिए.

यहाँ हम उपयोक्ता बर्ताव के लिए वही आदर्श लागू करते हैं:

  • उत्पाद दृश्य → product_view सिग्नल (संपारीट: 0.0)
  • गाड़ी में जोड़ें → add_to_cart सिग्नल (संपारीक: 0.35)
  • पू. → purchase सिग्नल (कभी नहीं): 1. 00)

सिग्नल एपेर्निकusa. kgm ( सत्र के साथ), शून्य- आरआई (कोई पहचान नहीं), और तौला हुआ (ऐ रसूल) देखो हरगिज़ उनका कहना न मानना

क्लाएंट फिंगरप्रिंटिंग (Zoo- updie पहचान)

कुकीज़ के बिना लिंक सत्रों को लिंक करने के लिए, हम प्रयोग करते हैं क्लाएंट- किनारा फिंगरप्रिंट. ब्राउज़र संकेतों से Hh की गणना करता है (समयक्षेत्र, स्क्रीन रेज़ोल्यूशन, प्रशंसार, कैनवास, फिंगरप्रिंट) और भेजें केवल हैश को /api/fingerprint.

सर्वर तब डीएमसी कि हैश एक गुप्त कुंजी के साथ, इसे किसी और जगह बंद कर दिया.

यह कोड मेरे द्वारा अनुकूल है बॉट पता लगाना परियोजनायही तकनीक, अलग उद्देश्य।

// 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);

अब हमारे पास एक स्थिर, साइट-कंडेंट है बिना कुकीज़ या स्थानीय वर्षा के. देखें देखें पूरा फिंगरप्रिंट.js श्रोत ( आमतौर पर ज़्यादातर लोगों की पसंद - नापसंद होती है ।

सिग्नल क़िस्म और भार

भिन्न कार्य स्तर भिन्न हैं. हम इस के साथ मॉडल बेस वजन्स.

सिग्नल क़िस्म: भार भार

// 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);
    }
}

ऐसा क्यों:

  • एकल पृष्ठ दृश्य (e)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;
}

क्योंकि तेज:

  • शुद्ध इनमेसी (कोई डीबी लिखना नहीं)
  • कोई सीरियलीकरण अप नहीं (मैं मेमोरीक)
  • कोई नेटवर्क कॉल नहीं (स्थानीय कैश)

प्रोफ़ाइल: एलईएसएंड सिग्नल

जब सत्र उच्च अभिप्राय दिखाता है (कारकार आगे, खरीदता है), हम संकेतों को किसी के लिए उन्‍नति करते हैं प्रोफ़ाइल जोड़ें.

प्रोप्रेशनप्रोसेसरेशन: लंबा- पद प्रोफ़ाइल

// 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;
}

फिर भी शून्य PII:

  • ProfileKey HMAC हैश (प्रयोग योग्य नहीं)
  • IdentificationMode हमें बताता है कि यह कैसे पहचाना गया (कॉम्पेड/लॉग/login)
  • सभी डाटा है बर्ताव- संकेत, व्यक्तिगत जानकारी नहीं

एलीवेशन: सत्र → प्रोफ़ाइल

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);
}

जब ज़मीन बड़े ज़ोरों के साथ ज़लज़ले में आ जाएगी

  • गाड़ी जोड़ने के बाद (उच्चप्रयोग)
  • खरीद के बाद (प्रयोग)
  • जब उपयोक्ता लगन में स्तर बदलता है (कैप्शन/ ty/login)

खण्ड परिभाषा:

हम दो भागों के लिए खण्डों को चिढ़ा दिया है. अब चलो वितरित करते हैं. खण्ड हैं कार्रवाई करने योग्य आउटपुट उन सभी संकेत संग्रहों का, वे जवाब देते हैं कि "यह किस तरह की दुकान है?"

पति - पत्नी के बीच फूट क्यों पड़ जाती है?

पारंपरिक खण्ड द्विचर है: आप या तो खण्ड में हैं या आप नहीं कर रहे हैं. यह पैदा समस्या पैदा करता है:

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

4 खरीदों के साथ एक ग्राहक समान रूप से 0 के साथ एक के साथ इलाज किया जाता है. यह गलत है.

नौसिखिक खण्ड प्रत्येक प्रोफ़ाइल एक अंक दें (0-1):

खुदा ने फरमाया है कि हम उसमें से किसी को भी हरा नहीं सकते |-----------|--------|-------------| जाएं 0 ("T) Description 0- 0. 0 गुज़र गया 2 गुज़र गया 0. 4 ("3 संतति) गुज़र गया 466Next 0. 840 Libisofs 5+6Y 1. 0z

अब आप व्यक्तिगत रूप से व्यक्तिगत रूप से कर सकते हैं: "सभी उच्च मूल्य" ग्राहकों को "बंद नहीं बंद" से कम अलग उपचार मिलता है।

खण्ड स्ट्रक्चर

// 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 अंक 1. 0 (exds दहलीज)
  • नियम 2: 0 (31 >= 0. 2) स्कोर 1. 0 (exds दहलीजs)
  • नियम 3: 0. 15 < 0. 0. 25) अंक 0. 0. 0. 7( भाग: 0. 15/ 0. 2)
  • अंतिम: (0.66 + 1. 02 + 0. 25×0. 2) / 1. 0x = 1. 0x = 0x 0.95
    1. 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 खण्ड होते हैं जो आम ई-कम्पर पैटर्न होते हैं:

सीजेके खण्ड |---------|------|-----------|----------| UNICKIT उच्च मूल्य ग्राहक DCAL 3+ खरीदते हैं, उच्च खर्च, हाल ही में WIV WP उपचार, वफ़ादारी प्रोग्राम “%s” EXACTCTECTCTECTCP ब्याज, उपकरण तकनीक उत्पाद सिफारिश UNDR Fhing CLONTH को आगे भेजें, बहु भेंट शैली सुझाव Git BRanghans कम कीमत सीमा, Salcuts अधिसूचना salver INNWENNACKS WELART2 सत्र, कोई खरीदिंग पर नहीं, पहले fagapacs प्रदान करता है Libisput slipt slipt 3+ गाड़ी आगे बढ़ते हैं, कुछ खरीदते हैं scips ईमेल INRWTHAT होम ब्याज, हाल ही में होम उत्पाद क्रूस-वेल [ पेज 11 पर बड़े अक्षरों में लेख की खास बात] IMTERT TIT TIT TANT TAT 5+ खरीदता है, 10+ सत्र रीक्शन, पुरस्कार BAR खोजकर्ताओं का कहना है कि हाल के सालों में यह संख्या तेज़ी से बढ़ती जा रही है ।

खण्ड समाप्त: सदस्यीय गतिविधि को बारी - बारी से इस्तेमाल किया जा रहा है

वह 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

पार्ट 3 पूर्ण बाहरी डाक कार्यान्वयन को कवर करता है: कार्य कतार, TixONOY home, तर्क, और स्केलिंग पैटर्न के लिए.

अगला क्या है

इस भाग से कवर किया गया:

  • शून्य- आरआई प्रोफ़ाइल बिल्डर (काप्टर सत्रों का सिंपलिंग)
  • आंकड़ा इनकोड में त्रुटि सदस्यता व वजन्ड नियमों के साथ सदस्यता
  • खण्ड सेवा निर्माण क्षमता के साथ

पार्ट 3 गहराई में चला जाता है:

  • आउटबॉक्स पैटर्न कार्यान्वयन - भरोसेमंद घटना प्रकाशन और एकल राउटर
  • कार्य कतार एसक्यूएल के साथ SKIP LOCKED वितरित संसाधन के लिए
  • गीत/ अनिल तत्काल काम अप (कोई पोल नहीं)
  • यूआई तथा पारदर्शिता - "आपका रुचि" जाल और खण्ड खोजकर्ता

खंड इस व्यवस्था के कार्ययोग्य आउटपुट हैं. वे जवाब देते हैं "यह कैसा दुकानर है?" trote स्कोरों के साथ, नहीं बाइनरी डोलों के साथ. और हर उपयोक्ता वास्तव में देख सकते हैं कि वे एक खंड में क्यों हैं.

Finding related posts...
logo

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